Python并发编程之多线程

本节内容

  • 什么是线程
  • 线程与进程的区别
  • 开启线程的两种方式
  • Thread对象的其他属性或方法
  • 守护线程
  • GIL全局解释器锁
  • 死锁和递归锁
  • 信号量 event 计时器
  •  线程queue

一 什么是线程

线程相对于进程更为轻量级,当一个进程启动同时也会启动一个主线程,多线程就是指在一个进程下创建多个线程并且这些线程共享地址空间。所以进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

二 线程与进程的区别

1 Threads share the address space of the process that created it; processes have their own address space.

2 Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.

3 Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.

4 New threads are easily created; new processes require duplication of the parent process.

5 Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.

6 Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.

总结上述区别,无非两个关键点,这也是我们在特定的场景下需要使用多线程的原因:

同一个进程内的多个线程共享该进程内的地址资源
创建线程的开销要远小于创建进程的开销(创建一个进程,就是创建一个车间,涉及到申请空间,而且在该空间内建至少一条流水线,但创建线程,就只是在一个车间内造一条流水线,无需申请空间,所以创建开销小)

三 开启线程的两种方式

开启线程的方式

方式一
from threading import Thread
import time

def sayhi(name):
    time.sleep(2)
    print('%s say hello' %name)

 if __name__ == '__main__':
    t=Thread(target=sayhi,args=('harry',))
    t.start()
    print('主线程')


方式二
from threading import Thread
import time

class Sayhi(Thread):
    def __init__(self,name):
         super().__init__()
         self.name=name
         def run(self):
         time.sleep(2)
         print('%s say hello' % self.name)

if __name__ == '__main__':
       t = Sayhi('harry')
       t.start()

基于多进程多线程实现套接字通信

 1 import socket
 2 from multiprocessing import Process
 3 from threading import Thread
 4 
 5 def create_socket():
 6      server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 7      server.bind(('127.0.0.1', 8080))
 8      server.listen(5)
 9      return server
10 
11 def talk(conn):
12 
13     while True:
14     try:
15         data = conn.recv(1024)
16         if data is None:break
17         conn.send(data.upper())
18     except ConnectionError:
19         break
20         conn.close()
21 
22 def communication(server):
23 
24     while True:
25         conn,add = server.accept()
26         t = Thread(target=talk, args=(conn,))
27             t.start()
28 
29 if __name__ == '__main__':
30      server = create_socket()
31      p1 = Process(target=communication, args=(server,))
32      p2 = Process(target=communication, args=(server,))
33      p1.start()
34      p2.start() 
View Code

编写一个简单的文本处理工具,具备三个任务,一个接收用户输入,一个将用户输入的内容格式化成大写,一个将格式化后的结果存入文件

 1 from threading import  Thread
 2     msg_l = []
 3         format_l = []
 4 
 5 def user_input():
 6     while True:
 7         text = input('请输入内容:')
 8         if text is None:continue
 9         msg_l.append(text)
10 
11 
12 def format_text():
13     while True:
14         if msg_l:
15         reg = msg_l.pop()
16         format_l.append(reg.upper())
17 
18 def save():
19     while True:
20         if format_l:
21         with open('db1.txt','a',encoding='utf-8') as f:
22         res = format_l.pop()
23         f.write('%s\n' %res)
24         f.flush()
25 
26 if __name__ == '__main__':
27             
28     t1 = Thread(target=user_input)
29         t2 = Thread(target=format_text)
30     t3 = Thread(target=save)
31 
32     t1.start()
33     t2.start()
34     t3.start()
View Code

四 Thread对象的其他属性或方法

Thread实例对象的方法
      # isAlive(): 返回线程是否活动的。 
      # getName(): 返回线程名。
      # setName(): 设置线程名。

threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

猜你喜欢

转载自www.cnblogs.com/harryblog/p/9126046.html