实现模块
- thread:多线程的底层支持模块,一般不建议使用;
- threading:对thread进行了封装,将一些线程的操作对象化
python 启动一个线程有两种方式
- thread.start_new_thread( print_time, (“Thread-1”, 2, ) )
- thread1 = myThread(1, “Thread-1”, 1)
函数方式
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import thread
import time
# 为线程定义一个函数
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )
# 创建两个线程
try:
thread.start_new_thread( print_time, ("Thread-1", 2, ) )
thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print "Error: unable to start thread"
while 1:
pass
类方式
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time
exitFlag = 0
class myThread (threading.Thread): #继承父类threading.Thread
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
print "Starting " + self.name
print_time(self.name, self.counter, 5)
print "Exiting " + self.name
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
thread.exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启线程
thread1.start()
thread2.start()
print "Exiting Main Thread"
threading.Thread类
- 构造函数:threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
group为保留参数,暂时无用;target为可调用的对象;name为线程的名字,注意多个线程可以有相同的名字;args是一个参数的tuple;kwargs为命令行参数的字典。
- name,getName(),setName(): 获取和设置线程的名字
- ident: 线程的唯一标识。线程启动后就会有,线程退出后被回收
- start(): 启动线程
- join(): 等待另一个线程结束后再运行。 join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的join()方法,直到线程A执行完毕后,才会继续执行线程B。
- is_alive(): 返回线程是否还存活着。
- daemon, isDaemon,setDaemon: 判断线程是否是守护线程,设置为守护线程(没有用户线程时自动退出的线程,如垃圾回收线程)。
- 参考链接: 多线程的socket服务器
在多线程编程中,t.setDaemon(True) / t.daemon = True
在底层模块中,只要主线程技结束了,其他线程都会结束 如果setDaemon(True),主线程结束,所有子线程都将结束 如果setDaemon(False),主线程将等待该线程结束,等同于你调用线程的join方法
join方法的作用是阻塞主进程,
- 参考资料 python多线程解析
守护进程
一般来说,所有的线程都完成工作以后,程序才会退出。
如果一个线程被设置为daemon,那么主线程退出的时候,它马上就退出了,这时候为了防止这种情况,可以调用join函数,线程调用join函数后,主线程就会等待子线程退出后才退出,而子线程执行的代码如果不能正常退出时那主线程也一直会等待,如果在join时加上一个超时时间,那主线程只等待设置的超时时间后主线程就退出。
线程间通信 - event
可以通过event,event.set()可以向线程发出信号,event.is_set()判断event是否被set
event = threading.Event()
# 发出event被set的信号
event.set()
# 判断event是否被set
event.is_set()
线程间同步 - lock
# 创建一个锁
lock = threading.Lock()
# 操作的时候先获取一个操作权限,生成一个Lock锁对象,同thread模块中的thread.allocate_lock,锁的用法也相同,使用acquire()获取,release()释放。
lock.acquire()
# 操作完成后,将锁释放
lock.release()
线程池
服务器处理链接最简单的做法是:当一个链接进来的时候,起一个线程来专门处理这个链接。当处理完这个链接以后,关掉这个链接,并结束掉这个线程。 当有很多大量短小的任务的时候,线程创建和销毁的开销很大。 为了提高效率,减少创建和销毁的开销,就预先创建一批线程,这一批线程就是线程池。