一,什么是多线程?

1.多线程的概念?

  说起多线程,那么就不得不说什么是线程,而说起线程,又不得不说什么是进程。

  进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

  以上是百度百科对进程的解释。

  进程可以简单的理解为一个可以独立运行的程序单位。它是线程的集合,进程就是有一个或多个线程构成的,每一个线程都是进程中的一条执行路径。

  那么多线程就很容易理解:多线程就是指一个进程中同时有多个执行路径(线程)正在执行。

  为什么要是用多线程?

  1.在一个程序中,有很多的操作是非常耗时的,如数据库读写操作,IO操作等,如果使用单线程,那么程序就必须等待这些操作执行完成之后才能执行其他操作。使用多线程,可以在将耗时任务放在后台继续执行的同时,同时执行其他操作。

  2.可以提高程序的效率。

  3.在一些等待的任务上,如用户输入,文件读取等,多线程就非常有用了。

  缺点:

  1.使用太多线程,是很耗系统资源,因为线程需要开辟内存。更多线程需要更多内存。

  2.影响系统性能,因为操作系统需要在线程之间来回切换。

  3.需要考虑线程操作对程序的影响,如线程挂起,中止等操作对程序的影响。

  4.线程使用不当会发生很多问题。

  总结:多线程是异步的,但这不代表多线程真的是几个线程是在同时进行,实际上是系统不断地在各个线程之间来回的切换(因为系统切换的速度非常的快,所以给我们在同时运行的错觉)。

2.多线程与高并发的联系。

  高并发:高并发指的是是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……。

  而多线程只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。

  多线程在高并发问题中的作用就是充分利用计算机资源,使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。

3.线程的创建

  首先引入包

    from threading import Thread

  然后实力化一个对象

    t = Thread(target=func,args=(i,))

  启动一个子线程线程
    t.start()

主线程默认等待所有子线程执行完毕结束运行

(1) 进程中可以包含多个线程

 def func(num):
time.sleep(random.uniform(0.1,1))
print("子线程" , num , os.getpid()) for i in range(10):
t = Thread(target=func,args=(i,))
t.start()

(2) 并发多线程 和 多进程,谁的速度快 => 多线程

 def func(num):
print("子线程" , num , os.getpid()) if __name__ == "__main__":
startime = time.perf_counter()
lst = [] for i in range(1000):
t = Thread(target=func,args=(i,))
t.start()
lst.append(t) for i in lst:
# print(i)
i.join() endtime = time.perf_counter()
print("多线程执行的时间:",endtime-startime)# 0.1063898997406085 # 多进程的执行时间
startime = time.perf_counter()
lst = []
for i in range(1000):
p = Process(target=func,args=(i,))
p.start()
lst.append(p) for i in lst:
i.join()
endtime = time.perf_counter()
print("多进程执行的时间:",endtime-startime) # 多进程执行的时间: 19.968611914504738

(3) 多线程共享同一份进程资源

  """线程和线程之间是异步并发的"""

 num = 1000
lst = []
def func():
# 异步并发程序
# time.sleep(1000)
global num
num -= 1 for i in range(1000):
t = Thread(target=func)
t.start()
lst.append(t) for i in lst:
i.join() print(num)

(4) 线程相关的函数

线程.is_alive() 检测线程是否仍然存在
线程.setName() 设置线程名字
线程.getName() 获取线程名字

from threading import Thread,current_thread,currentThread

1.currentThread().ident 查看线程id号
2.enumerate() 返回目前正在运行的线程列表
3.activeCount() 返回目前正在运行的线程数量

检测当前线程的名字

 def func():
# pass
time.sleep(0.5) t = Thread(target=func)
print(t)
t.start()
print(t.is_alive())
print(t.getName())
t.setName("producer_wangwen1号")#设置当前线程的名字
print(t.getName())
# 1.currentThread().ident 查看线程id号
 from threading import currentThread
def func():
print("子线程:",currentThread().ident) t = Thread(target=func)
t.start()
print("主线程:",currentThread().ident)

  2.enumerate()        返回目前正在运行的线程列表

 from threading import enumerate
from threading import currentThread
import time
from threading import Thread,current_thread,currentThread
def func():
print("子线程:", currentThread().ident)
time.sleep(0.5) for i in range(10):
t = Thread(target=func)
t.start() print(enumerate())
print(len(enumerate()))
 # 3.activeCount() 返回目前正在运行的线程数量 (了解)
from threading import activeCount
from threading import currentThread
def func():
print("子线程:",currentThread().ident)
time.sleep(0.5)
for i in range(10):
t = Thread(target=func)
t.start() print(activeCount())

# ### 守护线程: 等待所有线程全部执行结束之后,在终止,守护所有线程;
"""主线程默认等待所有的子线程;"""


 from threading import Thread
import time
def func1():
while True:
time.sleep(0.5)
print("我是子线程func函数") def func2():
print("func2 start ...")
time.sleep(3)
print("func2 end ... ") t1 = Thread(target=func1)
# 设置守护线程,在start调用之前进行设置 setDaemon
t1.setDaemon(True)
t1.start() t2 = Thread(target=func2)
t2.start() print("我是主线程 ... ")


# ### lock 线程锁,用来保证线程数据安全与进程锁同理,一旦使用异步程序会变为同步,一般用于抢票

 from threading import Thread,Lock
n = 0
def func1(lock):
global n for i in range(1000000):
lock.acquire()
# 写法一
n -= 1
lock.release() def func2(lock):
global n
for i in range(1000000):
# 写法二
with lock:
n += 1 if __name__ == "__main__":
# 创建一把锁
lock = Lock()
lst = []
for i in range(10):
# 10个线程专门负责加1
t1 = Thread(target=func1,args=(lock,))
# 10个线程专门负责减1
t2 = Thread(target=func2,args=(lock,))
t1.start()
t2.start()
lst.append(t1)
lst.append(t2) for i in lst:
i.join() print("主线程执行结束 ... ")
print(n)

# ### 信号量 Semaphore

  同时上多把锁,与进程锁原理是一样的

 from threading import Semaphore,Thread
import time
def func(i,sem):
with sem:
print(i)
time.sleep(10) sem = Semaphore(6)
for i in range(20):
Thread(target=func,args=(i,sem)).start()

python从入门到放弃之线程篇的更多相关文章

  1. dotnet 从入门到放弃的 500 篇文章合集

    本文是记录我从入门到放弃写的博客 博客包括 C#.WPF.UWP.dotnet core .git 和 VisualStudio 和一些算法,所有博客使用 docx 保存 下载:dotnet 从入门到 ...

  2. [Python 从入门到放弃] 6. 文件与异常(二)

    本章所用test.txt文件可以在( [Python 从入门到放弃] 6. 文件与异常(一))找到并自行创建 现在有个需求,对test.txt中的文本内容进行修改: (1)将期间的‘:’改为‘ sai ...

  3. [Python 从入门到放弃] 1. 列表的基本操作

    ''' 列表 Create By 阅后即焚 On 2018.1.29 ''' 1. 列表的定义 列表看起来好像其它编程语言中的数组,但列表具备更加强大的功能,它是Python完备的集合对象,现在,你可 ...

  4. Python从入门到放弃系列(Django/Flask/爬虫)

    第一篇 Django从入门到放弃 第二篇 Flask 第二篇 爬虫

  5. python从入门到放弃--线程进阶

    # ### 死锁,递归锁,互斥锁 from threading import Thread,Lock import time noodle_lock = Lock() kuaizi_lock = Lo ...

  6. python从入门到放弃之进程进阶篇

    什么我们得了解清楚什么是进程,进程就是系统分配的一个资源单位,真正在程序中干活得是线程,默认是每个进程中都拥有一个线程 然后我们在了解下什么是进程池这个概念 进程池是的数量是取决于我当前电脑的逻辑处理 ...

  7. Python 学习入门(21)—— 线程

    本文介绍了Python对于线程的支持,包括“学会”多线程编程需要掌握的基础以及Python两个线程标准库的完整介绍及使用示例. 1. 线程基础 1.1. 线程状态 线程有5种状态,状态转换的过程如下图 ...

  8. Python 学习入门(22)—— 线程同步

    Python主要通过标准库中的threading包来实现多线程.在当今网络时代,每个服务器都会接收到大量的请求.服务器可以利用多线程的方式来处理这些请求,以提高对网络端口的读写效率.Python是一种 ...

  9. [Python 从入门到放弃] 5. 文件与异常(一)

    1.文件操作: 文件操作包含读/写 从文件中读取数据 向文件写入数据 Python中内置了open()方法用于文件操作 (更多关于open()BIF介绍 阅读此篇) 基本模板: 1.获取文件对象 2. ...

随机推荐

  1. 一文学会JVM性能优化

    实战性能优化 1 重新认知JVM 之前我们画过一张图,是从Class文件到类装载器,再到运行时数据区的过程,现在咱们把这张图不妨丰富完善一下,展示了JVM的大体物理结构图. 执行引擎:用于执行JVM字 ...

  2. Wappalyzer(chrome网站分析插件)

    Wappalyzer是一款功能强大的.且非常实用的chrome网站技术分析插件,通过该插件能够分析目标网站所采用的平台构架. 网站环境.服务器配置环境.JavaScript框架.编程语言等参数,使用时 ...

  3. js-事件函数调用简化

    // 一般写法 function fn(event) { console.log(event) } div.onclick = function (event) { fn(event) } ===== ...

  4. Cobalt Strike系列教程第一章:简介与安装

    Cobalt Strike是一款超级好用的渗透测试工具,拥有多种协议主机上线方式,集成了提权,凭据导出,端口转发,socket代理,office攻击,文件捆绑,钓鱼等多种功能.同时,Cobalt St ...

  5. 【转载】Android Context 到底是什么?

    什么是Context? 一个Context意味着一个场景,一个场景就是我们和软件进行交互的一个过程.比如当你使用微信的时候,场景包括聊天界面.通讯录.朋友圈,以及背后的一些数据. 那么从程序的角度来看 ...

  6. ListenAndServe源码剖析

    使用goland追踪阅读ListenAndServe源码,剖析服务器启动流程 ListenAndServe阅读 func ListenAndServe(addr string, handler Han ...

  7. Nginx 配置详细文件

    概述 Nginx 是使用一个 master 进程来管理多个 worker 进程提供服务.master 负责管理 worker 进程,而 worker 进程则提供真正的客户服务,worker 进程的数量 ...

  8. 几款常见web扫描器的简要记录

    一.前期侦查 为了减少和目标系统的交互(防止触发报警),建议将目标站点镜像一份到本地 httrack(镜像网站到本地)  ====> 根据引导填入相关信息即可,使用非常简单 二.扫描 扫描分两种 ...

  9. Java面试题的个人总结

    面试总结 第一轮:电话初面 第二轮:技能面谈[技能职位尽量避免多谈处理上的作业] 第三轮:高管复试 第四轮:HR终究供认 一面:首要供认对阿里的意向度(假定异地更会考虑对作业地址(杭州)的意向度!阿里 ...

  10. 大学ACM学习笔记

    高斯消元 该来的总会来的系列 int gauss() { for(int i=1;i<=n;i++)//按照列来枚举,当前之前i-1列全消完了 { int k=i; for(int j=i+1; ...