一,什么是多线程?

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. 数据结构javascript实现

    电脑配置 CPU:AMD X4 640 内存: 宏想 DDR3 1600MHz 8g 主板:华擎 980DE3/U3S3 R2.0 浏览器:chrome 79.0.3945.88(正式版本) (64 ...

  2. scrapy实例:爬取天气、气温等

    1.创建项目 scrapy startproject weather # weather是项目名称 scrapy crawl spidername开始运行,程序自动使用start_urls构造Requ ...

  3. kotlinx.android.synthetic.** 坑点

    Kotlin通过添加 apply plugin: 'kotlin-android-extensions' 可以直接使用layout id 名称获取当前view对象,详细使用如下: //layout & ...

  4. electron打包出现有文件下载不全的情况

    1.根据提示下载相应的东西 https://blog.csdn.net/az44yao/article/details/85242442 具体可以看这个链接 2.有个小坑,如果到了按照链接1的过程,遇 ...

  5. MSSQL注入:显错注入及反弹注入

    前言: MSSQL注入攻击是最为复杂的数据库攻击技术,由于该数据库功能十分强大,存储过程以及函数语句十分丰富,这些灵活的语句造就了新颖独特的攻击思路. MSSQL的显错注入操作: 以联合查询为例: 猜 ...

  6. 阿里云ubuntu 16.04 搭建pptpd 第二版

    前言:1.我常用的服务器在国内,但我又有某方面的需求,所以想要搭建一个pptpd的服务器    2.但我又不常用,所以感觉阿里云包年包月的不划算,所以准备采用阿里云按量付费的实例来搭建pptpd,并形 ...

  7. Druid-代码段-1-5

    所属文章:池化技术(一)Druid是如何管理数据库连接的? 本代码段对应流程1.4,抛弃连接: //丢弃连接 public void discardConnection(Connection real ...

  8. 题解:SPOJ1026 Favorite Dice

    原题链接 题目大意 给你一个n个面的骰子,每个面朝上的几率相等,问每个面都被甩到的期望次数 题解 典型的赠券收集问题. 我们考虑当你手上已有\(i\)种不同的数,从集合中任选一个数得到新数的概率,为\ ...

  9. day_93_11_25爬虫一requests,项目框架

    总结 nginx反向代理与正向代理. 正向带里就是,客户端通过中转服务器,访问其它他服务器的数据. 反向代理就是用户访问中转服务器,看起来就像和这台服务器交互一样. nginx动静分离. 当客户端访问 ...

  10. Vue 知识点个人总结

    Vue 脚手架 脚手架 3 的版本 ---- webpack 4 cnpm install -g @vue/cli-----全局安装组件 vue create myapp-----命令行创建项目 或者 ...