【day9】线程threading/线程池threadpool/多进程multiprocessing

python基础

1 线程与进程

  • 进程:一个进程就是一个程序。
  • 线程:线程就是进程里面最小的执行单元。
  • 线程是在进程里面的,干活的还是线程。
  • 一个进程里面最少有一个线程,可以有多个线程
  • 每个线程之间都是互相独立的
  • 没有真正意义上的并发,你的电脑的cpu是几核的,那么最多只能同时运行几个任务。
  • python里面的多线程,是利用不了多核cpu的,只能利用一个核心的cpu。因为Python有GIL 全局解释器锁,只能放一个cpu。
  • 有些情况下,你用多线程的时候会发现它比单线程速度还慢。
  • 多进程,是可以利用多核cpu的。
  • 多进程和多线程是为了提高效率。
  • 多线程任务适用于io密集型任务。
    • IO分为磁盘IO,网络IO,如下载、上传文件、打开网站等
  • 多进程任务适用于cpu密集型任务。
    • cpu密集型:比如排序、科学计算等

2 创建线程

获取不到方法返回结果,如果想要返回结果,可以在方法外定义全局变量all_res =[],然后将方法中想返回的值加入到list中。

不能直接target=方法名(参数),这样就相当于target=None,只会去执行该方法,但不会为该方法创建线程。

1 t = threading.Thread(target=方法名,args=(参数1,)) #args参数列表为一个元组,当只有一个参数时,必须在后面加一个逗号;当有多个参数时,末尾的逗号可加可不加

3 启动线程

  • 启动线程
1 t = threading.Thread(target=方法名,args=(参数1,)) 
2 t.start()
  • 返回当前线程名称

    threading.current_thread()

4 时间差、结果返回错误

问题:总是先打印时间、返回结果,再打印方法中的输出信息。时间差、结果返回错误。

原因:每个线程之间是互相独立的。主线程分配3个子线程干活后,无论子线程是否完成任务,主线程都继续往下跑,所以打印时间差、获取返回结果是错误的。

 1 #!/usr/bin/python
 2 # -*- coding:utf-8 -*-
 3 # Author:hwm
 4 import threading,time
 5 all_res = [] #这是用来存储函数的结果的
 6 def run(name):
 7     print('子线程,',threading.current_thread())
 8     time.sleep(60)
 9     print('【%s】哈哈哈'%name)
10     name = 'hhj'+name
11     all_res.append(name)
12 start = time.time()
13 
14 #threads = [] #存放所有的子线程
15 
16 for i in range(3):#先统一启动所有的子线程,python文件中总共有4个线程,1个主线程,3个子线程
17     t = threading.Thread(target=run,args=(str(i),))
18     #threads.append(t) #
19     t.start()
20 end = time.time()
21 print('1=====',end-start)
22 print('2=====',all_res)
1 子线程, <Thread(Thread-1, started 9060)>
2 子线程, <Thread(Thread-2, started 10224)>
3 子线程, <Thread(Thread-3, started 7808)>
4 1===== 0.0009999275207519531
5 2===== []
6 【0】哈哈哈
7 【1】哈哈哈
8 【2】哈哈哈
View Result

5 线程等待

5.1 线程等待sleep(s)-wrong

问题:由于主线程加入了sleep,sleep时间结束后,主线程就继续往下跑,这个时间子线程不一定全部执行完成。所以打印时间差、返回结果,也不一定是准确的。

但是从运行结果可以看出来,加入了sleep后,返回结果不是为空的了。说明时间差、返回结果错误,是由于主线程不等待返回结果就继续执行造成的。

注:主线程是从头到尾执行所有代码,发现:all_res返回为空;它是不是等待子进程是否执行完。 所以主线程执行到最后时,sleep(6)等待6秒后,子线程也就都执行完了。

 1 #!/usr/bin/python
 2 # -*- coding:utf-8 -*-
 3 # Author:hwm
 4 import threading,time
 5 all_res = [] #这是用来存储函数的结果的
 6 def run(name):
 7     print('子线程,',threading.current_thread())
 8     time.sleep(5)
 9     print('【%s】哈哈哈'%name)
10     name = 'hhj'+name
11     all_res.append(name)
12 start = time.time()
13 
14 #threads = [] #存放所有的子线程
15 
16 for i in range(3):#先统一启动所有的子线程
17     t = threading.Thread(target=run,args=(str(i),))
18     #threads.append(t) #
19     t.start()
20 time.sleep(6)
21 end = time.time()
22 print('1=====',end-start)
23 print('2=====',all_res)
1 子线程, <Thread(Thread-1, started 9912)>
2 子线程, <Thread(Thread-2, started 6744)>
3 子线程, <Thread(Thread-3, started 6952)>
4 【2】哈哈哈
5 【1】哈哈哈
6 【0】哈哈哈
7 1===== 6.0
8 2===== ['hhj2', 'hhj0', 'hhj1']
View Result

5.2 线程等待join()--wrong

 问题:循环中加入t.join(),表示等待当前的子线程完成后,再启动下一个子线程,从而会导致线程串行执行的问题。

另外,t.join()不可以放在循环外面,因为这样的话,相当于主线程在等待最后一个启动的线程,但是由于线程之间是独立的,所以无法确定到底哪个线程会先执行结束,所以结果也是不准确的。

 1 #!/usr/bin/python
 2 # -*- coding:utf-8 -*-
 3 # Author:hwm
 4 import threading,time
 5 all_res = [] #这是用来存储函数的结果的
 6 def run(name):
 7     print('子线程,',threading.current_thread())
 8     time.sleep(5)
 9     print('【%s】哈哈哈'%name)
10     name = 'hhj'+name
11     all_res.append(name)
12 start = time.time()
13 #threads = [] #存放所有的子线程
14 for i in range(3):#先统一启动所有的子线程
15     t = threading.Thread(target=run,args=(str(i),))
16     #threads.append(t)
17     t.start()
18     t.join()
19 end = time.time()
20 print('1=====',end-start)
21 print('2=====',all_res)
1 子线程, <Thread(Thread-1, started 6824)>
2 【0】哈哈哈
3 子线程, <Thread(Thread-2, started 6592)>
4 【1】哈哈哈
5 子线程, <Thread(Thread-3, started 9420)>
6 【2】哈哈哈
7 1===== 15.001000165939331
8 2===== ['hhj0', 'hhj1', 'hhj2']
View Result

5.3 线程等待 active_count()-correct

while threading.active_count()!=1:pass
#判断当前活动的线程是几个,如果是1的话,说明子线程都已经执行完成了。那么主线程就可以继续执行了;如果不是1的话,说明子线程未执行完成,则循环等待直至子线程运行结束。

此写法简洁,推荐使用。

 1 #!/usr/bin/python
 2 # -*- coding:utf-8 -*-
 3 # Author:hwm
 4 import threading,time
 5 all_res = [] #这是用来存储函数的结果的
 6 def run(name):
 7     print('子线程,',threading.current_thread())
 8     time.sleep(5)
 9     print('【%s】哈哈哈'%name)
10     name = 'hhj'+name
11     all_res.append(name)
12 start = time.time()
13 for i in range(3):#先统一启动所有的子线程
14     t = threading.Thread(target=run,args=(str(i),))
15     t.start()
16 while threading.active_count()!=1:pass  # 当前活动的线程是几个,如果为1,说明子线程都已经执行完成了
17 end = time.time() 18 print('1=====',end-start) 19 print('2=====',all_res)
1 子线程, <Thread(Thread-1, started 6632)>
2 子线程, <Thread(Thread-2, started 9420)>
3 子线程, <Thread(Thread-3, started 4628)>
4 【1】哈哈哈
5 【0】哈哈哈
6 【2】哈哈哈
7 1===== 5.015000104904175
8 2===== ['hhj1', 'hhj0', 'hhj2']
View Result

5.4 线程等待 逐个join() -correct

思路:

1、先统一启动所有子线程,将线程放在一个列表中。

2、主线程再逐一去循环线程列表,并逐一等待子线程执行结束。

3、全部执行结束后,主线程再继续往下跑,打印时间差、返回结果就会是正确的了。

 1 #!/usr/bin/python
 2 # -*- coding:utf-8 -*-
 3 # Author:hwm
 4 import threading,time
 5 all_res = [] #这是用来存储函数的结果的
 6 def run(name):
 7     print('子线程,',threading.current_thread())
 8     time.sleep(5)
 9     print('【%s】哈哈哈'%name)
10     name = 'hhj'+name
11     all_res.append(name)
12 start = time.time()
13 threads = [] #存放所有的子线程
14 for i in range(3):#先统一启动所有的子线程
15     t = threading.Thread(target=run,args=(str(i),))
16     threads.append(t)
17     t.start()
18 for t in threads:
19     t.join()#逐一等待已启动的子线程
20 end = time.time()
21 print('1=====',end-start)
22 print('2=====',all_res)
1 子线程, <Thread(Thread-1, started 6452)>
2 子线程, <Thread(Thread-2, started 7708)>
3 子线程, <Thread(Thread-3, started 12556)>
4 【2】哈哈哈
5 【0】哈哈哈
6 【1】哈哈哈
7 1===== 5.001000165939331
8 2===== ['hhj2', 'hhj0', 'hhj1']
View Code
1 子线程, <Thread(Thread-1, started 6452)>
2 子线程, <Thread(Thread-2, started 7708)>
3 子线程, <Thread(Thread-3, started 12556)>
4 【2】哈哈哈
5 【0】哈哈哈
6 【1】哈哈哈
7 1===== 5.001000165939331
8 2===== ['hhj2', 'hhj0', 'hhj1']
View Code

猜你喜欢

转载自www.cnblogs.com/xhybk/p/9419207.html
今日推荐