day30线程(Threads)

1、开启线程

一、什么是线程:
1.进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程。
2.主进程中的线程称为主线程,其他开启的线程称为子线程
二、为什么用线程:
进程有两个缺点:
1.进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。
2.进程在执行的过程中如果遇到阻塞,例如等待输入,整个过程就会挂起。即使进程中有些工作不依赖于输入的数据,也将无法执行。
# 而这就是为什么还要用线程
代码:
from threading import Thread def task():
print('子线程') if __name__ == '__main__':
t = Thread(target=task)
t.start()
print('主线程')

2、GIL全局解释器锁

GIL全局解释器锁的特点:
1.python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。
2.虽然python解释器可以“运行”多个线程,但在任意时刻只有一个线程在解释器中执行。
3.由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。
常识:
1.python代码在解释器中执行,绝大部分在用:cpython解释器,少部分用:pypy解释器
2.GIL锁在解释器中存在,他只能在cpython解释器中,pypy解释器中不存在
3.起一个垃圾回收线程,起一个正常执行的线程,垃圾回收还没有回收完毕,另一个线程可能会抢占资源
4.设置一把全局解释器锁(GIL锁),有了这把锁,就保证同一时刻,只能有一个线程执行,只要线程想执行,那么,就必须拿到这把GIL锁
5.如果是IO密集型:选择线程,因为io不会用到cpu内核,线程在进程里了
6.如果是计算密集型:选择进程 # 计算密集型用多进程,计算io密集型用多线程

3、进程和线程的区别

一、开启效率的较量
from multiprocessing import Process
from threading import Thread
import time
# 开启进程的时间
def task():
time.sleep(1)
print(123) if __name__ == '__main__':
ctime = time.time()
p = Process(target=task)
p.start()
p.join()
print(time.time() - ctime)
# 输出结果:1.0815215110778809 # 开启线程的时间
def task():
time.sleep(1)
print(123) if __name__ == '__main__':
ctime = time.time()
t = Thread(target=task)
t.start()
t.join()
print(time.time() - ctime)
# 输出结果:1.0080914497375488
# 结论:进程消耗比线程消耗大很多
二、多线程和多进程进行pid的比较
# 进行pid的较量
from multiprocessing import Process
from threading import Thread
import os
def task():
print('hello',os.getpid()) if __name__ == '__main__':
# 注:开启多个进程,每个进程都有不同的pid
p1 = Process(target=task)
p2 = Process(target=task)
p1.start()
p2.start()
print('主进程/主进程pid',os.getpid()) # 注:在主进程下开启多个线程,每个线程都跟主进程pid一样
t1 = Thread(target=task)
t2 = Thread(target=task)
t1.start()
t2.start()
print('主进程/主进程pid',os.getpid())
# 结论:开启多进程,每个进程的pid都是不同的。在主程序下开启多线程,每个线程pid都和主程序pid一样。

4、Thread类的其他方法

一、Thread实例对象的方法:
1.is_alive():返回线程是否活动
2.getName();返回线程的名称
3.setName():设置线程名称
二、threading模块提供的一些方法:
1.threading.currentThread():返回当前的线程变量
2.threading.enumerate():返回一个包含正在运行的线程的list。
3.threading.activeCount():范慧慧正在运行的线程数量,与len(threading.enumerate())有相同的结果。
代码:
from threading import Thread
import time def task():
time.sleep(1)
print(123) if __name__ == '__main__':
t = Thread(target=task)
t.start()
print(t.is_alive()) # 返回线程是否活动
print(t.getName()) # 返回线程的名称
t.setName('mmm') # 设置线程的名称
print(t.getName())

5、守护线程

	p.isDaemon和t.setDaemon(True)的特点:主进程(线程)结束,子进程(线程)也随之结束。也根本不会运行子进程(线程)的程序。# 注意守护进程一定要放在start()之前,不然不会运行
代码:
from threading import Thread
import time
import os def task():
time.sleep(1)
print('my is %s'%(os.getpid())) if __name__ == '__main__':
t =Thread(target=task)
t.setDaemon(True) # 跟进程不一样,进程的是p.isDaemon
t.start()
print('主线程')
print(t.is_alive())
# 返回结果:主线程,True,特点主线程结束,子线程也结束。

6、同步锁(互斥锁)

代码:
from threading import Thread,Lock
import time def task(lock):
global n
lock.acquire() # 上锁
time.sleep(1)
n -= 1
lock.release() # 释放锁 if __name__ == '__main__':
n = 10
l = []
lock = Lock()
for i in range(10):
t = Thread(target=task,args=(lock, ))
t.start()
l.append(t)
for j in l:
j.join()
print(n) # 结果肯定为0,由原来的并发执行变成串行,牺牲了执行效率保证了数据安全
# 补充:Lock在Process中为进程锁,在Thread中为互斥锁。

7、信息量(Semaphore)

# Semaphore:信息量可以理解为多把锁,同时允许多个进程量更改数据
代码:
from threading import Thread,Semaphore
import time
import random
sm = Semaphore(2) # 允许两个线程 def task(i):
sm.acquire()
print('线程:%s进来了'%i)
time.sleep(random.randint(1,3))
print('线程:%s出去了'% i)
sm.release() if __name__ == '__main__':
for i in range(6):
t = Thread(target=task,args=(i, ))
t.start()

8、Enent事件

Enent事件的用法:
1.一些线程需要等到其他线程执行完成之后才能执行,类似于发射信号
2.比如一个线程等待另一个线程执行结束在继续执行
代码:
from threading import Thread, Event
import time def girl(event):
print('女神正在谈恋爱中')
time.sleep(3)
event.set() # 发射信号
print('女神分手了') def boy(i, event):
print('屌丝:%s正在等待女神分手' % i)
event.wait() # 正在等待
print('屌丝:%s开始展开追求' % i) if __name__ == '__main__':
event = Event()
t = Thread(target=girl, args=(event,))
t.start() for i in range(5):
t1 = Thread(target=boy, args=(i, event))
t1.start()

day30线程(Threads)的更多相关文章

  1. ARM官方《CMSIS-RTOS教程》之线程Threads

    创建线程Creating Threads 一旦RTOS开始运行,就会有很多系统调用来管理和控制活跃的线程.默认情况下,main()函数自动被创建为第一个可运行的线程.在第一个例子里我们使用main() ...

  2. 笔记 线程(threads)

    线程:CPU使用的基本单元(线程ID.程序计数器.寄存器集合.栈). 多线程:一个进程有多个线程 多线程的优点: 增加响应度:当一个交互程序部分阻塞,该程序能继续执行 一个应用程序在同一地址空间有多个 ...

  3. 在Linux下面如何查看tomcat已经使用多少线程(Threads)

    先用 ps aux |grep tomcat 查看tomcat的 PID 再用 ps -T -p <PID>|wc -l 查看线程

  4. SYSBIOS学习笔记---线程(Threads)

    在SYS/BIOS中,广义上指被处理器执行的任何独立的指令流.线程是一个能够调用一个函数或者中断服务程序的单点控制.在sysbios系统中一共有硬件中断(HWI).软件中断(SWI).任务(Task) ...

  5. Android---53---多线程下载

    采用HttpURLConnection HttpURLConnection从继承URLConnection,它也可以被用来发送到指定的网站GET求 POST求. 办法: int getResponse ...

  6. 进程,线程,GIL,Python多线程,生产者消费者模型都是什么鬼

    1. 操作系统基本知识,进程,线程 CPU是计算机的核心,承担了所有的计算任务: 操作系统是计算机的管理者,它负责任务的调度.资源的分配和管理,统领整个计算机硬件:那么操作系统是如何进行任务调度的呢? ...

  7. Python并发编程之线程消息通信机制任务协调(四)

    大家好,并发编程 进入第四篇. 本文目录 前言 Event事件 Condition Queue队列 总结 . 前言 前面我已经向大家介绍了,如何使用创建线程,启动线程.相信大家都会有这样一个想法,线程 ...

  8. Perl多线程(1):解释器线程的特性

    线程简介 线程(thread)是轻量级进程,和进程一样,都能独立.并行运行,也由父线程创建,并由父线程所拥有,线程也有线程ID作为线程的唯一标识符,也需要等待线程执行完毕后收集它们的退出状态(比如使用 ...

  9. 【学习笔记】tensorflow队列和线程

    目录 Tensorflow队列 同步执行队列 队列管理器 异步执行队列 线程协调器 在使用TensorFlow进行异步计算时,队列是一种强大的机制. 为了感受一下队列,让我们来看一个简单的例子.我们先 ...

随机推荐

  1. 0x02

    #include<bits/stdc++.h> using namespace std; int n,a[10][10],vis[10],ans,b[10][10]; inline int ...

  2. 当src获取不到图片,onerror可指定一张默认的图片

    <img src="img/789.png" onerror="javascript:this.src='img/123.png';" alt=" ...

  3. Web实时通信,SignalR真香,不用愁了

    前言 对于B/S模式的项目,基础的场景都是客户端发起请求,服务端返回响应结果就结束了一次连接:但在很多实际应用场景中,这种简单的请求和响应模式就显得很吃力,比如消息通知.监控看板信息自动刷新等实时通信 ...

  4. 组件通过props属性传值

    组件之间的传值 组件是一个单独功能模块的封装,有属于自己的data和methods,一个组件的 data 选项必须是一个函数 为什么必须是函数:因为只有当data是函数时,不同实例调用同一个组件时才会 ...

  5. easypoi导出动态表头excel

    easypoi导出动态表头excel 1: springBoot项目maven依赖: <dependency> <groupId>cn.afterturn</groupI ...

  6. 经过4次优化我把python代码耗时减少95%

    背景交代 团队做大学英语四六级考试相关服务.业务中有一个care服务,购买了care服务考试不过可以全额退款,不过有一个前提是要完成care服务的任务,比如坚持背单词N天,完成指定的试卷. 在这个背景 ...

  7. ArrayList 源码分析和自定义ArrayList实现

    概述 ArrayList 是基于数组实现的,是一个能自动扩展的动态数组. ArrayList 是线程不安全的,多线程情况下添加元素会出现数组越界的情况,而且数组赋值操作不是原子操作,会导致多线程情况下 ...

  8. 反射的妙用:C#通过反射动态生成类型继承接口并实现

    起因 最近想自己鼓捣个RPC,想着简化RPC调用方式,直接申明接口,然后根据接口的属性去配置RPC调用的相关信息.有一种说法叫申明式调用. 简单来说就是,申明一个interface,动态继承并实例化, ...

  9. @RestController注解的作用

    原文出自"https://www.cnblogs.com/yaqee/p/11256047.html" 一.在Spring中@RestController的作用等同于@Contro ...

  10. GoLang设计模式15 - 策略模式

    策略模式是一种行为型设计模式.通过策略模式,可以在运行时修改一个对象的行为. 接下来仍然是通过例子来了解策略模式.比如说内存缓存,这是我们在开发中经常使用的东西,大家应该都有一定的了解,接下来就用内存 ...