Java教程

05-5 万字长文:实现多线程(结尾)

本文主要是介绍05-5 万字长文:实现多线程(结尾),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

5.6 Python 多线程的问题

你好,我是悦创。由于 Python 中 GIL 的限制,导致不论是在单核还是多核条件下,在同一时刻只能运行一个线程,导致 Python 多线程无法发挥多核并行的优势。

GIL 全称为 Global Interpreter Lock,中文翻译为全局解释器锁,「其最初设计是出于数据安全而考虑的。」

在 Python 多线程下,每个线程的执行方式如下:

  • 获取 GIL
  • 执行对应线程的代码
  • 释放 GIL

可见,某个线程想要执行,必须先拿到 GIL,我们可以把 GIL 看作是通行证,并且在一个 Python 进程中,GIL 只有一个。拿不到通行证的线程,就不允许执行。这样就会导致,即使是多核条件下,一个 Python 进程下的多个线程,同一时刻也只能执行一个线程。

不过对于爬虫这种 IO 密集型任务来说,这个问题影响并不大。而对于计算密集型任务来说,由于 GIL 的存在,多线程总体的运行效率相比可能反而比单线程更低。

5.7 避免 GIL

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

前面开头已经提到:因为 「GIL」 的存在,所以不管我们开了多少线程,同一时间始终只有一个线程在执行。那我们该如何避免 「GIL」 呢?

那这样的话,我们「不开线程」不就行,(它的的存在已经无法避免,那我们选择不使用它不就相当于不存在嘛)。那这是,你会想:那不开线程我们开啥呢?

问的好!

我们来开:「进程」,那怎么说?别急!请听我细细道来。

比方你有 「3 个 CPU」(当然,你可能有更多,这里就按 「3」 个 「CPU」来为例子),那我们就开 「3 个进程」就好。一个 「CPU」 上运行就好。

「Ps:我们的进程是可以同时运行的。」

我们可以看一下下面的图片:

「任务管理器」

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

我们 「任务管理」 上的每一项都是一个进程。

多进程比多线程不好的地方是什么呢?

多进程的创建和销毁开销也会更大,成本高。

你可能线程可以开许多的线程,但你的进程就是看你的 「CPU」 数量。

进程间无法看到对方数据,需要使用栈或者队列进行获取。

每个进程之间都是独立的。

就好像我们上面的谷歌浏览器和我们的 Pycharm 是没有任何关系的,谷歌浏览器上面的数据肯定不可能让 Pycharm 看到。这就是我们所说的进程之间的独立性。

如果你想要一个进行抓取数据,一个进行调用数据,那这时是不能直接调用的,需要你自己定义个结构才能使用。>>> 编程复杂度提升。


学员问题:任务管理器上面超过五六个进程。都是进程的话,怎么能开那么多呢?

答:我们一个 CPU 不止能执行一个进程,就比如我的一个 CPU 里面密麻麻有许多进程。(比方我现在开六个进程)并发执行的。只不过计算机执行的速度非常快,这里我简单讲一下哈。这是计算机原理的课。

不管是任何操作系统,现在就拿单核操作系统来说:我们假设现在只有一个 CPU ,一个 CPU 里面六个「进程」,同一时间它只有一个进程在运行。不过我们计算执行速度非常快,这个程序执行完,它就会执行一个「上下文切换」,执行下一个。(因为,它执行的速度非常快,你就会感觉是并发执行一样。)

实际上,一个 CPU 同一时间只有一个进程在执行,一个进程里面它只有一个线程在执行。(当然,这个单核是五六年前了。现在肯定至少有双核。

那就说有第二个 CPU 了。

而第二个和  CPU 上面又有许多个 「进程」,两个 「CPU」 是互不相干。

那这时候,第一个 CPU 上面运行一个进程,而我们的第二个 CPU 上面也有一个进程,两个是互补相干。 (就相当于你开了两台电脑。)

但是同一个 CPU 在同一时间只有一个就进程。(不管你(电脑)速度多么快,实际上本质上(在那一秒)只有一个进程在执行。「如果你是双核,那就有两个进程。(四核就有四个进程)」

Python 有个不好的地方,刚刚上面讲到,如果我们有两个 CPU 那就有两个进程在执行(那四个 CPU 就是四个进程在执行),**但是因为 Python 当中存在着 GIL,它即使有四个 CPU 每次也只有一个线程能进去,**也就是说:同一时间当中,一个 CPU 上的一个进程中的一个线程在执行。剩下的都不能运行,我们的 Python 不能利用多核。

如果,大家用的是 C、Java、Go 这种的就没有这个说法了。

5.8 线程池

我找了许多包,这个包还是不错的:Pip install threadpool

# project = 'Code', file_name = '线程池', author = 'AI悦创'
# time = '2020/3/3 0:05', product_name = PyCharm
# code is far away from bugs with the god animal protecting
#    I love animals. They taste delicious.

import time
import threadpool

# 执行比较耗时的函数,需要开多线程
def get_html(url):
	time.sleep(3)
	print(url)
# 按原本的单线程运行时间为:300s
# 而多线程池的化:30s
# 使用多线程执行 telent 函数
urls = [i for i in range(100)]
pool = threadpool.ThreadPool(10) # 建立线程池

# 提交任务给线程池
requests = threadpool.makeRequests(get_html, urls)

# 开始执行任务
for req in requests:
	pool.putRequest(req)
pool.wait()

 

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

这篇关于05-5 万字长文:实现多线程(结尾)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!