文档章节

线程

o
 osc_1ee7cxmx
发布于 2018/08/06 19:43
字数 1510
阅读 0
收藏 0
def

「深度学习福利」大神带你进阶工程师,立即查看>>>

1、启动一个线程

import threading
import time

def run(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))

if __name__ == '__main__':
    t = threading.Thread(target=run,args=('Chen',))
    t.start()
print('The main process is running!')

结果如下:

The main process is running!
Chen is running the threading!!

注:由此看出,线程启动后已与程序本身的线程(主线程)已经没有关系了,并不会等待主线程运行完毕后再运行手动启动的线程。

2、join()函数的意思是等调用该函数的实例线程运行完毕之后在运行主线程,例如在上边代码的基础上,在t.start()后边增加t.join(),则运行结果如下:

Chen is running the threading!!
The main process is running!

如果手动启动多个线程,要等所有的线程运行完毕后在运行主线程,则需要循环,如下:

import threading
import time

def run(name):
    time.sleep(4)
    print('{name} is running the threading!!'.format(name = name))
def run1(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))
    time.sleep(1)

if __name__ == '__main__':
   t1 = threading.Thread(target=run,args=('Chen',))
   t2 = threading.Thread(target=run1, args=('Chen2',))
   t1.start()
   t2.start()
   t2.join()

print('The main process is running!')

结果如下:

Chen2 is running the threading!!
The main process is running!
Chen is running the threading!!

模型如下:

 

3、如果要等所有的程序运行完毕之后在运行主程序,则需要遍历所有手动启动的线程

import threading
import time

def run1(name):
    time.sleep(4)
    print('{name} is running the threading!!'.format(name = name))
def run2(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))
    time.sleep(1)
def run3(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))
t_list = []
if __name__ == '__main__':
    t1 = threading.Thread(target=run1,args=('Chen1',))
    t2 = threading.Thread(target=run2,args=('Chen2',))
    t3 = threading.Thread(target=run3,args=('Chen3',))
    t1.start()
    t2.start()
    t3.start()
    t_list.append(t1)
    t_list.append(t2)
    t_list.append(t3)
    for t in t_list:
        t.join()

print('The main process is running!')

这样主程序就会等所有的手动线程启动完成之后才会运行!

4、daemon thread 守护线程,守护线程就是伴随着其他线程的消亡而自动消亡的,他的执行情况不重要

import threading
import time

def run(name):
    time.sleep(1)
    print('I am the child of daemon threading {name}'.format(name = name))

def main():
    print('The main threading is running!!')
    r = threading.Thread(target=run,args=('main',))
    r.start()
    time.sleep(2)  //这的时间大于run的时间,所以在main执行完后,run也执行完比,但当这的时间小于run()的时间,那么run()就没有执行完毕,即程序运行的结果为:The main threading is running和
//The threading has runned,就没有I am the child of daemon threading main了
if __name__ == '__main__': m = threading.Thread(target=main) m.setDaemon(True) //设置main为守护线程,当主线程执行完毕后,不管守护线程是否执行完毕,守护线程及子线程全部结束 m.start() //守护线程的设置一定要在线程开始之前设置(很正常的逻辑,小细节) m.join(timeout = 8) //这里的8sec表示最多不超过8s,当在小于8s的时间内守护线程运行完毕,主线程的运行时间可以小于8 print('The threading has runed
总结:守护线程是伴随其守护的线程而存亡的,当守护的线程结束时,守护线程及其子线程一并结束。

5.1、线程锁(互斥锁Mutex)

在同一个进程中,线程是共享空间的,当在同一个进程中启动多个线程时,而多个线程调用同一份数据时,此时就有可能出乱子了。例如:

import threading
import time

def run():
    global num
    time.sleep(1)
    lock.acquire()
    num -= 1
    lock.release()
    print('The result of num is:',num)

lock = threading.Lock()
num = 1000
t_list = []
if __name__ == '__main__':
    for i in range(1000):
        t = threading.Thread(target=run,args=())
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()

加锁的主要目的在于每一次只能有一个线程对数据进行修改,而不至于出现第一个线程还没运行结束,第二个线程就过来取数据,这样两个线程运行的结果是一样的。运算模型如下

5.2递归锁 就时在父线程中加锁,然后在子线程中也加锁

启动多个线程,每个线程调用同样的两个方法A和B,两种方法分别处理同一块数据,就有可能出现互斥锁的情况,故需要再增加一层锁,就称谓递归锁!!

5.3 信号量(semaphore):就是同时允许多少个线程对同一块数据进行处理。使用方法如下:

import threading, time
def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" % n)
    semaphore.release()
num = 0
semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行

if __name__ == '__main__':
    for i in range(20):
        t = threading.Thread(target=run, args=(i,))
        t.start()

5.4Timer

import threading
def hello():
    print("hello, world")
t = threading.Timer(10,hello)
t.start()  # after 30 seconds, "hello, world" will be printed

6、Event()事件,就好比两个人再对话一样,是一个时间,事件里边包括两个人。

import threading
import time

event = threading.Event()

def talk_1(name):
    count = 1
    event.set()   #设置的是讲话
    while True:
        if count <= 5:
            print('{name} is talking!!'.format(name = name))
        elif count > 5 and count <= 10:
            event.clear()
            print('我不讲了,我要看着你讲!!')
        else:
            count = 0
            event.set()
        count += 1
        time.sleep(1)

def talk_2(name):
    while True:
        if not event.isSet():
            print('{name} begin to talk!!'.format(name = name))
        else:
            event.wait()
            print('{name} is looking at Lilei!!'.format(name = 'Lucy'))
        time.sleep(1)

if __name__ == '__main__':
    t = threading.Thread(target=talk_1,args=('Lilei',))
    t.start()
    c = threading.Thread(target=talk_2,args=('Lucy',))
    c.start()

事件设置的是Lilei在讲话,Lucy在看着leilei讲话,讲完后,切换。event.wait()只有在事件被设置后才运行。

7、queue

queue有几种类型,先进先出,first in first out, 后进先出, last in first out, 还有一个优先权

import queue

q = queue.Queue()生成一个先进先出的queue

q = queue.Lifoqueue()生成一个后进先出的queue

q = queue.PriorityQueue(maxsize = internal)优先队列再生成实例是要求确定队列的大小,即需要确定maxsize的数值,压栈是需要确定队列的先后顺序例如:

q.put((1,20))

q.put((2,30))

q.put((0,50))把队列中第一个位置放50,第二个位置放20,第三个位置放30.

 消费者买包子模型,就是生产者不停的往蒸笼里放包子,做好的包子不断的被消费者购买,蒸笼的大小是不变的,这也是queue区别与list的重要的一个点!!

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

功能之前,感叹号有什么作用? - What does the exclamation mark do before the function?

问题: !function () {}(); 解决方案: 参考一: https://stackoom.com/question/Fl0I/功能之前-感叹号有什么作用 参考二: https://oldbug.net/q/Fl0I/What-does-the-exclamation-mark-do-......

富含淀粉
43分钟前
3
0
微服务分布式构架开发实战 附下载地址

微服务是一种软件架构风格,目标是将一个复杂的应用拆分成多个服务模块,每个模块专注单一业务功能对外提供服务,并可以独立编译及部署,同时各模块间互相通信彼此协作,组合为整体对外提供完...

Idea
今天
18
0
AppEmit v0.9.5 新功能 chrome 浏览器调用本地应用程序 支持打开 编辑 金山 wps office,  excel  ppt

AppEmit v0.9.5 新功能 浏览器调用本地应用程序 支持打开 编辑 金山 office 更多主页 能在以及几乎所有支持websock浏览器,包括chrome各个版本,支持打开 编辑 金山 wps office, excel ppt ...

AppEmit
今天
11
0
Git(学习二)----->Tortoise Git(图形化工具) 安装

下载: 本人使用版本为2.4.0.2有需要的可以从网盘下载,也可以百度找资源 链接:https://pan.baidu.com/s/13Vu0VNUQMZNFKLFhl6VzDw 提取码:y27p 一、安装 步骤1:安装向导 步骤2:许可介绍 步...

安然_oschina
今天
7
0
TarsGo 服务获取自定义模版(配置)值

作者:amc 导语:之前的文章中我们介绍了如何使用TarsGo创建HTTP服务和TARS RPC服务,本篇文章中,我们将介绍如何在TarsGo服务中获得自定义模板的配置值。 TARS 模版是什么? TARS 框架中,有...

TARS基金会
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部