文章摘抄笨小孩: https://blog.csdn.net/weixin_40481076/article/details/101594705.
- 线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行
线程与进程的区别:
- 线程共享内存,进程独立内存
- 线程启动速度块,进程启动速度慢,运行时速度没有可比性
- 同一个进程的线程间可以直接交流,两个进程想通信,必须通过一个中间代理来实现
- 创建新线程很简单,创建新进程需要对其父进程进行一次克隆
- 一个线程可以控制和操作同一线程里的其他线程,但是进程只能操作子进程
python主要是通过thread和threading这两个模块来实现多线程支持。python的thread模块是比较底层的模块,python的threading模块是对thread做了一些封装
2.1 普通创建
def run(n):
print('task',n)
time.sleep(1)
print('2s')
time.sleep(1)
print('1s')
time.sleep(1)
print('0s')
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=run,args=('t1',)) # target是要执行的函数名(不是函数),args是函数对应的参数
t2 = threading.Thread(target=run,args=('t2',))
t1.start()
t2.start()
2.2 自定义
class MyThread(threading.Thread):
def __init__(self,n):
super(MyThread,self).__init__() #重构run函数必须写
self.n = n
def run(self):
print('task',self.n)
time.sleep(1)
print('2s')
time.sleep(1)
print('1s')
time.sleep(1)
print('0s')
time.sleep(1)
if __name__ == '__main__':
t1 = MyThread('t1')
t2 = MyThread('t2')
t1.start()
t2.start()
2.3 守护线程
def run(n):
print('task',n)
time.sleep(1)
print('3s')
time.sleep(1)
print('2s')
time.sleep(1)
print('1s')
if __name__ == '__main__':
t=threading.Thread(target=run,args=('t1',))
t.setDaemon(True)
t.start()
print('end')
2.4 多线程共享全局变量
g_num = 100
def work1():
global g_num
for i in range(3):
g_num+=1
print('in work1 g_num is : %d' % g_num)
def work2():
global g_num
print('in work2 g_num is : %d' % g_num)
if __name__ == '__main__':
t1 = threading.Thread(target=work1)
t1.start()
time.sleep(1)
t2=threading.Thread(target=work2)
t2.start()
2.5 主线程等待子线程结束
def run(n):
print('task',n)
time.sleep(2)
print('5s')
time.sleep(2)
print('3s')
time.sleep(2)
print('1s')
if __name__ == '__main__':
t=threading.Thread(target=run,args=('t1',))
t.setDaemon(True) #把子线程设置为守护线程,必须在start()之前设置
t.start()
t.join() #设置主线程等待子线程结束
print('end')
2.6 互斥锁
def work():
global n
lock.acquire()
temp = n
time.sleep(0.1)
n = temp-1
lock.release()
if __name__ == '__main__':
lock = Lock()
n = 100
l = []
for i in range(100):
p = Thread(target=work)
l.append(p)
p.start()
for p in l:
p.join()
2.7 递归锁
def func(lock):
global gl_num
lock.acquire()
gl_num += 1
time.sleep(1)
print(gl_num)
lock.release()
if __name__ == '__main__':
gl_num = 0
lock = threading.RLock()
for i in range(10):
t = threading.Thread(target=func,args=(lock,))
t.start()
2.8 信号量
def run(n,semaphore):
semaphore.acquire() #加锁
time.sleep(3)
print('run the thread:%s\n' % n)
semaphore.release() #释放
if __name__== '__main__':
num=0
semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
for i in range(22):
t = threading.Thread(target=run,args=('t-%s' % i,semaphore))
t.start()
while threading.active_count() !=1:
pass
else:
print('----------all threads done-----------')
线程池在系统启动时即创建大量空闲的线程,程序只要将一个函数提交给线程池,线程池就会启动一个空闲的线程来执行它。当该函数执行结束后,该线程并不会死亡,而是再次返回到线程池中变成空闲状态,等待执行下一个函数。
3.1 实现线程池
#encoding:utf-8
import time
import threadpool
import random
import threading
def sayhello(str): #执行方法
sleep_seconds=random.randint(1, 3)
print '线程名称:%s,参数:%s,睡眠时间:%s'%(threading.current_thread().name,str,sleep_seconds)
time.sleep(sleep_seconds)
name_list =['aa','bb','cc','dd'] #总共需要执行4个线程
start_time = time.time() #开始时间
pool = threadpool.ThreadPool(2) #创建2个线程
requests = threadpool.makeRequests(sayhello, name_list)
for req in requests:
pool.putRequest(req) #将每个请求添加到线程池中
pool.wait() #等待线程执行完后再执行主线程
print '总共运行时间:%d second'% (time.time()-start_time)