并发编程 - 多线程 - 总结

时间:2021-02-26 18:03:08
进程,线程:
进程只是用来把资源集中到一起的(进程只是个资源单位,或者说资源集合),线程才是cpu上的执行单位。
区别:
1.同一个进程内的多个线程共享该进程内的地址资源
2.创建线程的开销要远小于创建进程的开销(创建一个进程,就是创建一个车间,涉及到申请空间,而且在该空间内建至少一条流水线,但创建线程,就只是在一个车间内造一条流水线,无需申请空间,所以创建开销小
1.创建线程的两种方式:
并发编程 - 多线程 - 总结并发编程 - 多线程 - 总结
 1 import time
 2 from threading import Thread
 3 
 4 def sayhi(name):
 5     time.sleep(2)
 6     print('%s is say hello'%name)
 7 
 8 if __name__ == "__main__":
 9     t = Thread(target=sayhi,kwargs={'name':'alice'})
10     # t = Thread(target=sayhi,args=('alice',))
11     t.start()
12 
13     print('主线程')
方式一
并发编程 - 多线程 - 总结并发编程 - 多线程 - 总结
 1 from threading import Thread
 2 import time
 3 
 4 class Sayhi(Thread):
 5     def __init__(self,name):
 6         super().__init__()
 7         self.name = name
 8 
 9     def run(self):
10         time.sleep(2)
11         print('%s is say hello'%self.name)
12 
13 if __name__ == "__main__":
14     t = Sayhi('alice')
15     t.start()
16 
17     print('主线程')
方式二
2.多进程多线程的区别: 
1.开进程的开销远大于开线程
2.进程之间地址空间是隔离的,
同一进程内开启的多个线程是共享该进程的地址空间的
3.开多个进程,每个进程都有不同的pid
在主进程下开启多个线程,每个线程的pid都和主进程的pid一样
并发编程 - 多线程 - 总结并发编程 - 多线程 - 总结
 1 #1.
 2 from multiprocessing import Process
 3 from threading import Thread
 4 import time
 5 
 6 def work(name):
 7     print('%s is working'%name)
 8     time.sleep(2)
 9     print('%s is done'%name)
10 
11 if __name__ == "__main__":
12     # p = Process(target=work,args=('alice',))
13     # p.start()
14 
15     t = Thread(target=work,args=('alice',))
16     t.start()
17 
18     print('主进程/主线程')
19 """
20 主进程/主线程
21 alice is working
22 alice is done
23 """
24 """
25 alice is working
26 主进程/主线程
27 alice is done
28 """
29 #2.
30 from multiprocessing import Process
31 from threading import Thread
32 
33 n=100
34 def task():
35     global n
36     n=0
37 
38 if __name__ == "__main__":
39     # p = Process(target=task)
40     # p.start()
41     # p.join()   # 彼此隔离的 n: 100
42     t = Thread(target=task,)
43     t.start()
44     t.join()   # 共享地址空间 n: 0
45     print('n:',n)
46 """
47 n: 100
48 """
49 """
50 n: 0
51 """
52 # 3.
53 from multiprocessing import Process,current_process
54 from threading import Thread
55 import os
56 
57 def task():
58     print(current_process().pid)
59     print('hello,pid:',os.getpid(),"ppid:",os.getppid())
60 
61 if __name__ == "__main__":
62     p1 = Process(target=task)
63     p2 = Process(target=task)
64     p1.start()
65     p2.start()
66     # t1 = Thread(target=task)
67     # t2 = Thread(target=task)
68     # t1.start()
69     # t2.start()
70 
71     print(current_process().pid)
72     print('主进程/主线程 pid:',os.getpid(),'ppid:',os.getppid())
73 """
74 主进程/主线程 pid: 6908 ppid: 3888
75 hello,pid: 21096 ppid: 6908
76 hello,pid: 20228 ppid: 6908
77 """
78 """
79 hello,pid: 24068 ppid: 3888
80 hello,pid: 24068 ppid: 3888
81 主进程/主线程 pid: 24068 ppid: 3888
82 """
多进程多线程的区别
3.Thread对象的其他属性或方法:
Thread实例化对象的方法:
1.t.isAlive() / t.is_alive() # 返回线程是否活动中
2.t.getName() / t.name # 返回线程名
3.t.setName() # 设置线程名
threading模块提供的一些方法:
threading.currentThread() # 返回当前的线程变量
threading.enumerate() # 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount() # 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
主线程等待子线程结束!!
并发编程 - 多线程 - 总结并发编程 - 多线程 - 总结
 1 from threading import Thread,currentThread,current_thread,active_count,enumerate,activeCount
 2 import time
 3 
 4 def task():
 5     print('%s is running'%currentThread().getName())
 6     time.sleep(2)
 7     print('%s is done'%current_thread().getName())
 8 
 9 if __name__ == "__main__":
10     t = Thread(target=task,)
11     t.start()
12     # t.join()
13     print(t.getName())
14     t.setName('儿子')
15     print(t.name)
16     currentThread().setName('主线程')
17     print(current_thread().name)
18     print(t.is_alive())
19     # t.join()
20     print(active_count())
21     print(enumerate())
22     print(t.isAlive())
23     print(t.name)
24     print(t.getName())
25     # currentThread().
26     print(len(enumerate()))
27     print(activeCount())
28     print(active_count())
29     # t.join()
30     print(t.isAlive())
31     time.sleep(3)
32     print(t.isAlive())
Thread对象的其他属性或方法
4.守护线程:
守护进程(守护线程)会等待主进程(主线程)运行完毕后被销毁
运行完毕并非终止运行:
1.对主进程来说:运行完毕指的是主进程代码运行完毕
2.对主线程来说:运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
详细解释:
1.主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束。
2.主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。

t.daemon = True
t.setDaemon(True)
并发编程 - 多线程 - 总结并发编程 - 多线程 - 总结
 1 from threading import Thread
 2 import time
 3 
 4 def sayhi(name):
 5     print('start-------')
 6     time.sleep(2)
 7     print('%s say hello'%name)
 8 
 9 if __name__ == "__main__":
10     t = Thread(target=sayhi,args=('alice',))
11     # t.daemon = True
12     t.setDaemon(True)
13     t.start()
14 
15     print('主线程')
16     print(t.is_alive())
17 """
18 start-------
19 主线程
20 True
21 """
22 
23 # 思考下述代码的执行结果有可能是哪些情况?为什么?
24 from threading import Thread
25 import time
26 
27 def foo():
28     print(123)
29     time.sleep(1)
30     print("end123")
31 
32 def bar():
33     print(456)
34     time.sleep(3)
35     print("end456")
36 
37 if __name__ == '__main__':
38     t1=Thread(target=foo)
39     t2=Thread(target=bar)
40 
41     t1.daemon=True
42     t1.start()
43     t2.start()
44     print("main-------")
45 """   # 主线程运行完毕 指的是 所有的非守护线程统统运行完毕
46 123
47 456
48 main-------
49 end123
50 end456
51 """
守护线程