码迷,mamicode.com
首页 > 编程语言 > 详细

多线程学习总结

时间:2018-02-01 20:40:22      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:实例   生成   需要   read   生产者   and   __init__   []   执行   

 

一 起线程

以函数的方式以一个线程

import threading
import time

def run(n):
    print("task ", n)
    time.sleep(2)
    print("task done", n)

start_time = time.time()
t_objs = []  # 存线程实例
for i in range(10):
    t = threading.Thread(target=run, args=("t-%s" % i,))  # 起线程
    t.start()
    t_objs.append(t)  # 为了不阻塞后面线程的启动,不在这里join,先放到一个列表里

for t in t_objs:  # 循环线程实例列表,等待所有线程执行完毕
    t.join()

print("----------all threads has finished...")
print("cost:", time.time() - start_time)

测试时间略大于2秒. 主线程和这个主线程所启动的子线程是并行的,主线程的执行和子线程无关,要想在程序中让主线程等待子线程 的执行,只能加join() 方法.

 二 以类的方式起线程

import threading
import time


class MyThread(threading.Thread):
    def __init__(self, n, sleep_time):
        super(MyThread, self).__init__()
        self.n = n
        self.sleep_time = sleep_time

    def run(self):
        # 重写父类的run 函数,所以只能是这个函数名
        print("runnint task ", self.n)
        time.sleep(self.sleep_time)
        print("task done,", self.n)

t1 = MyThread("t1", 2)
t2 = MyThread("t2", 4)

t1.start()
t2.start()

t1.join()
t2.join()
# 写上这两句之后,先把t1和t2执行完之后再执行print("main thread...."),不然就是先执行print("main thread....")

二 守护线程

import threading
import time

def run(n):
    print("task ",n )
    time.sleep(5)
    print("task done",n,threading.current_thread())

start_time = time.time()
t_objs = [] #存线程实例
for i in range(5):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.setDaemon(True) #把当前线程设置为守护线程
    t.start()
    t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里

for t in t_objs: #循环线程实例列表,等待所有线程执行完毕,只有当这里面的线程执行完之后程序才往下走,
    t.join()

time.sleep(1)
print("----------all threads has finished...",threading.current_thread(),threading.active_count())
print("cost:",time.time() - start_time)

如果没有设置守护线程,

技术分享图片

可以看出,是先把print 语句执行完之后,程序再等待执行所有子线程执行完的, 

加上守护线程之后的结果

技术分享图片

程序没有等待子线程执行完之后就退出了.  

把join() 加上之后(也就是把那两行代码的注释取消之后)的结果:

技术分享图片

  这里主要是比较他们执行的顺序.

 三 线程锁

import threading
import time


def run(n):
    lock.acquire()  # 加锁,
    global num
    num += 1
    time.sleep(0.2)
    lock.release()  # 解锁

lock = threading.Lock()  # 生成一个线程锁实例
num = 0
t_objs = []  # 存线程实例
for i in range(5):
    t = threading.Thread(target=run, args=("t-%s" % i,))
    t.start()
    t_objs.append(t)  # 为了不阻塞后面线程的启动,不在这里join,先放到一个列表里

for t in t_objs:  # 循环线程实例列表,等待所有线程执行完毕
    t.join()

print("all threads has finished :", threading.current_thread(), threading.active_count())

print("num:", num)

加锁之后,在锁中间部分程序就是串行了,Python3中解释器自动加锁了,所以可以不再加锁,

四 递归锁

import threading, time


def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num

def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res = run1() #这里执行run1,而run1中已有锁,所以需要递归锁,使用和平常锁一样,只是在声明时声明为递归锁就行
    print(--------between run1 and run2-----)
    res2 = run2()
    lock.release()
    print(res, res2)

num, num2 = 0, 0
lock = threading.RLock() #声明为递归锁
for i in range(1):
    t = threading.Thread(target=run3)
    t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print(----all threads done---)
    print(num, num2)

递归锁和线程锁用法是一样的,只是需要在声明时声明成递归锁就行

五 信号量

import threading, time


def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" % n)
    semaphore.release()

if __name__ == __main__:
    semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行
    for i in range(22):
        t = threading.Thread(target=run, args=(i,))
        t.start()
while threading.active_count() != 1:
    pass  # print threading.active_count()
else:
    print(----all threads done---)
    # print(num)

    # 信息号和线程锁用法一样,只是在声明时声明一个信息号就行

信息号和线程锁用法一样,只是在声明时声明一个信号量就行

六 事件Event

import time
import threading


event = threading.Event()

def lighter():
    count = 0
    event.set() #先设置绿灯
    while True:
        if count >5 and count < 10: #改成红灯
            event.clear() #把标志位清了
            print("\033[41;1mred light is on....\033[0m")
        elif count >10:
            event.set() #变绿灯
            count = 0
        else:
            print("\033[42;1mgreen light is on....\033[0m")
        time.sleep(1)
        count +=1

def car(name):
    while True:
        if event.is_set(): #代表绿灯
            print("[%s] running..."% name )
            time.sleep(1)
        else:
            print("[%s] sees red light , waiting...." %name)
            event.wait()
            print("\033[34;1m[%s] green light is on, start going...\033[0m" %name)


light = threading.Thread(target=lighter,)
light.start()

car1 = threading.Thread(target=car,args=("Tesla",))
car1.start()

事件程序只有三种状态,set(), wait(),clear(),可以在这三种状态下分别做事情,

七 线程队列

# 生产者 消费者模型
import threading,time

import queue

q = queue.Queue(maxsize=10)  # 定义一个共用的线程queue

def Producer(name):
    count = 1
    while True:
        q.put("包子%s" % count)
        print("生产了包子",count)
        count +=1
        time.sleep(0.5)

def Consumer(name):
    #while q.qsize()>0:
    while True:
        print("[%s] 取到[%s] 并且吃了它..." %(name, q.get()))
        time.sleep(1)

p = threading.Thread(target=Producer,args=("zhangsan",))
c = threading.Thread(target=Consumer,args=("lishi",))
c1 = threading.Thread(target=Consumer,args=("wangwu",))

p.start()
c.start()
c1.start()

 

多线程学习总结

标签:实例   生成   需要   read   生产者   and   __init__   []   执行   

原文地址:https://www.cnblogs.com/liuqianli/p/8400651.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!