并发编程(2) thread 详解

Posted on Posted in python

多线程

开启线程

方法一

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=('abc',))                                     
    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('abc')
    t.start()
    print('主线程')

其他属性和方法

Thread

  • isAlive() 返回线程是否活动的
  • getName() 返回线程名
  • setName() 设置线程名

threading 模块提供的方法

  • threading.currentThread() 返回当前的线程变量
  • threading.enumerate() 返回一个包含正在运行的线程的 list。 正在运行指线程启动后,结束前,不包括启动前和终止后的线程
  • threading.activeCount() 返回正在运行的线程数量,与 len(threading.enumerate()) 有相同的结果
from threading import Thread
import threading

def work():
    import time
    time.sleep(1)
    print(threading.current_thread().getName())

if __name__ == '__main__':
    t = Thread(target=work)
    t.start()

    print(threading.current_thread().getName())
    print(threading.current_thread()) # 主线程
    print(threading.enumerate()) # 连同主线程在内还有两个运行的线程
    print(threading.active_count())
    print('主线程/主进程')

主线程等子线程结束

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=('abc',))                                      
    t.start()                                                                   
    t.join()                                                                    
    print('主线程')                                                             
    print(t.is_alive()) 

=====>

abc say hello
主线程
False

守护线程

  • 主进程在其他代码结束后就已经算运行完毕了,然后主进程会一直定非守护的子进程都运行完毕后回收子进程资源
  • 主线程再其他非守护线程运行完毕后才算运行完毕。因为主线程的结束以为着整体都回收
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=('abc',))                                      
    t.setDaemon(True)                                                                                                                                             
    t.start()                                                                   
    print('主线程')                                                             
    print(t.is_alive())

信号量

信号量也是一种锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行。互斥锁就是饭店有一个座位,信号量就是饭店有5个座位。每次处理的数量不一样

from threading import Thread, Semaphore
import time, threading

def func():
    sm.acquire()
    print('%s get sm' % threading.current_thread().getName())
    time.sleep(3)
    sm.release()

if __name__ == '__main__':
    sm = Semaphore(5)
    for i in range(23):
        t = Thread(target=func)
        t.start()
  • Semaphore 管理一个内置计数器
  • 每当调用 acquire() 内置计数器 -1
  • 每当调用 release() 内置计数器 +1
  • 计数器不能小于0; 当计数器为 0 时,acquire() 将阻塞线程直到其他线程调用 release()

Event

线程信号标志,默认为假

from threading import Event
event.isSet() # 返回 event 的状态值
event.wait() # 如果 event.isSet() == Flase 将阻塞进程
event.set() # 设置 event 的状态值为 True,所有阻塞池的线程激活进入就绪状态,等待操作系统调度
event.clear() # 恢复 event 的状态值为 False
"""
多个线程连接mysql,再连接之前确保mysql服务正常才让那些工作线程去连接,如果连接不成功,尝试重新连接
"""
from threading import Thread, Event
import threading
import time, random

def check_mysql():
    print('[%s] 正在检查mysql' % threading.current_thread().getName())
    time.sleep(random.randint(2,4))
    event.set()

def conn_mysql():
    count = 1
    while not event.is_set():
        if count > 3:
            raise TimeoutError('时间超时')
        print('<%s> 第%s次尝试连接' % (threading.current_thread().getName(), count))
        event.wait(0.5)
        count += 1
    print('<%> 连接成功' % threading.current_thread().getName())

if __name__ == '__main__':
    event = Event()
    conn1 = Thread(target=conn_mysql)
    conn2 = Thread(target=conn_mysql)
    check = Thread(target=check_mysql)

    conn1.start()
    conn2.start()
    check.start()

定时器

from threading import Timer                                                     
                                                                                
def hello():                                                                                                                                                      
    print('hw')                                                                 
                                                                                
t = Timer(1,hello) # 1s 后执行                                                  
t.start()

线程队列

一、先进先出

import queue                                                                    
                                                                                
q = queue.Queue()                                                               
q.put('1')                                                                      
q.put('2')                                                                      
q.put('3')                                                                      
                                                                                
print(q.get())                                                                  
print(q.get())                                                                  
print(q.get())

=====>

1
2
3

二、先进后出-堆栈

import queue                                                                    
                                                                                
q = queue.LifoQueue()                                                                                                                                             
q.put('1')                                                                      
q.put('2')                                                                      
q.put('3')                                                                      
                                                                                
print(q.get())                                                                  
print(q.get())                                                                  
print(q.get())

=====>

3
2
1

优先级队列

import queue                                                                                  
                                                                                              
q = queue.PriorityQueue()                                                                     
# put 一个元组,元组的第一个元素是优先级,通常是数字,也可以是非数字的比较,数字越小优先级越高                                                                    
q.put((20,'a'))                                                                               
q.put((10,'b'))                                                                               
q.put((40,'c'))                                                                               
                                                                                              
print(q.get())                                                                                
print(q.get())                                                                                
print(q.get()) 

=====>

(10, 'b')
(20, 'a')
(40, 'c')
» 转载请注明来源:若我若鱼 » 并发编程(2) thread 详解

Leave a Reply

Your email address will not be published. Required fields are marked *

three × 3 =