记录博客 ZH-BLOG

Python 线程 threading 模块

时间:2018-07-24 15:11:26分类:python

1.以指定方法的形式创建线程

import threading,time
# 以指定方法的形式创建线程
def radom_print():
    for i in range(0,10):
        print('out: %s'%i)

ta=threading.Thread(target=radom_print)
tb=threading.Thread(target=radom_print)
ta.start()
tb.start()

传递参数:

print('cats','dog','fogs',sep='&')

thread_obj=threading.Thread(target=print,args=['cats','dog','fogs'],kwargs={'sep':'&'})
thread_obj.start()

2.以继承的方式创建线程

import threading
#  以继承类,实现run方法创建线程
class MyThread(threading.Thread):
    def run(self):
        for i in range(0,10):
            print('out: %s' % i)

ta=MyThread()
tb=MyThread()
ta.start()
tb.start()

3.join() 阻塞线程

import threading,time

def random_print():
    for i in range(0,10):
        print('out: %s'%i)
        time.sleep(1)

print('begin')
ta=threading.Thread(target=random_print)
ta.start()
if ta.isAlive():    # 线程是否活动状态未结束
    ta.join()   # join() 阻塞主线程直至ta线程结束
print(ta.isAlive()) # False 线程结束
print('end')

4.Event() 通过信号使线程等待、运行

1.wait() 线程等待,直至标识为 True

2.clear() 设置标识为 False

3.set() 设置标识为 True

import threading,time

def random_print():
    event.wait()    # waitting for True
    for i in range(0,10):
        print('out: %s'%i)

def print_t2():
    event2.wait()  # waitting for True
    for i in range(0, 10):
        print('Thread2 out: %s' % i)

event=threading.Event()
event2=threading.Event()
print('main begin.')
event.clear()   # setting False
event2.clear()
my_thread=threading.Thread(target=random_print)
my_thread.start()
t2=threading.Thread(target=print_t2)
t2.start()
time.sleep(3)
event.set() # setting True
time.sleep(2)
event2.set()
print('main end.')

5.对应共享数据加锁保证数据同步

import threading, time

class MyThread(threading.Thread):
	""" 期望值5000000,多次运行结果均不同 """
    def run(self):
        global count
        print(self.name)
        for i in range(100000):
            count += 10

count = 0
thread_list = []
for i in range(5):
    thread_list.append(MyThread())

for t in thread_list:
    t.start()

time.sleep(3) # 确保线程运行完毕
print(count)

造成的原因是:当某一个线程获取 count,进入循环之前,其它的线程已经改变了count值(变大),而该线程使用的 count 值未同步,计算后值变小

加锁:使 count 只能被一条线程获取更改

class MyThread(threading.Thread):
    def run(self):
        lock.acquire() # 获取锁
        global count
        for i in range(0,10):
            count+=10
        lock.release() # 释放锁

count=0
lock=threading.RLock()
thread_list=[]
for i in range(0,5):
    thread_list.append(MyThread())
for mythread in thread_list:
    mythread.start()
print(count)

6.守护线程

使用 True 或 False 判断一个线程是否为守护线程。

当没有活着的非守护线程,整个 Python 程序自动退出。

import threading,time

class MyThread(threading.Thread):
    def run(self):
        for i in range(0,20):
            print(self.name+': out %s'%i)
            time.sleep(2)

def random_print():
    for i in range(0,10):
        print('Thread-2: out %s'%i)
        time.sleep(1)

print('main: begin.')
ta=MyThread()
ta.daemon=True
tb=threading.Thread(target=random_print)
# tb.daemon=True    # non-daemon线程全部结束,daemon线程自动结束 (tb线程先结束后,ta线程自动死亡)
ta.start()
tb.start()
print('main: end.')

7.条件变量 Condition

1. condition.acquire() 获取锁

2. condition.release() 释放锁

3. condition.wait() 线程等待

4. condition.notify(n) 唤醒至多 n 个线程 

5. condition.notify_all() 唤醒 condition 所有线程

import threading

class Producer(threading.Thread):
    def run(self):
        global bread
        while True:
            condition.acquire() # 获取锁
            print('查看面包是否卖出:%s'%bread)
            if bread>0:
                condition.wait()    # 等待卖出
            else:
                bread+=1    # 生产一个面包
                print('生产了一个面包...')
                condition.notify_all()  # 唤醒其它线程,不影响锁,锁不会因此释放
            condition.release() # 释放锁

class Consumer(threading.Thread):
    def run(self):
        global bread
        while True:
            condition.acquire()
            print('询问是否有面包:%s'%bread)
            if bread<1:
                condition.wait()    # 等待生产面包
            else:
                bread-=1
                print('卖出一个面包...')
                condition.notify_all()
            condition.release()

bread=0
condition=threading.Condition()
for i in range(0,3):
    Producer().start()
    Consumer().start()

8. 队列

队列是线程安全的,可以很好的用来处理多生产、多消费模式。

queue.Queue(maxsize)  maxsize 设置队列上限,<= 0 无上限。

import threading,queue

class Procuder(threading.Thread):
    def run(self):
        while True:
            bread_queue.put('bread')
            print('生产了一个面包...   %s'%bread_queue.qsize())

class Consumer(threading.Thread):
    def run(self):
        while True:
            bread_queue.get()
            print('卖出了一个面包...   %s'%bread_queue.qsize())

bread_queue=queue.Queue(1)
Procuder().start()
Consumer().start()