Python 多线程问题

2015-07-07 20:20:58 +08:00
 latteczy
https://gist.github.com/smartczy/35e692064b775dcc3e17

上面的代码分别用多线程和普通方式抓取页面信息。但是二者运行时间相差无几,大约都是0.7+秒。这里应该不是CPU密集型,所以多线程应该有效率的提高才对。不知是何原因?
最近在学习Python的多线程,请大神多多指教!
4041 次点击
所在节点    Python
28 条回复
realityone
2015-07-07 20:28:15 +08:00
你在 q 里面再加一句 time.sleep(5) 然后观察下就知道问题在哪里了



`t.join()`
RichardZhiming
2015-07-07 20:32:02 +08:00
尽量使用多进程,gil是Python的历史遗留问题
latteczy
2015-07-07 20:36:14 +08:00
@RichardZhiming 嗯,只是想搞明白这个Python的多线程是怎么回事
zhyu
2015-07-07 20:36:55 +08:00
join([timeout])
Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates – either normally or through an unhandled exception – or until the optional timeout occurs.
latteczy
2015-07-07 20:40:32 +08:00
@realityone 加上time.sleep(5)之后结果是21秒多,还是不太明白,麻烦能否再指点一下。是t.join()有问题么?
latteczy
2015-07-07 20:43:09 +08:00
@zhyu 额,join()是要等待该线程结束才能再起其他的线程啊。也就是说加上join()就跟单线程一样咯?
Shazoo
2015-07-07 20:43:33 +08:00
threads = []
for i in range(4):
t = threading.Thread(target=q, args=(hosts[i],))
threads.append(t)
t.start()

for t in threads:
t.join()

这样应该会快些。
onlyice
2015-07-07 20:47:35 +08:00
alexapollo
2015-07-07 20:56:35 +08:00
建议你用多进程 multiprocessing 模块。
python 的线程机制比较弱,一般用多进程或异步解决这个问题。
latteczy
2015-07-07 21:02:54 +08:00
@alexapollo 我知道,我只是想弄明白Python的多线程是怎么回事。而且对于这段代码,多线程应该是会有效率上的提高的,但是我并没测试出有提高。所以想弄明白是怎么回事。
alexapollo
2015-07-07 21:08:03 +08:00
@latteczy GIL,查了就懂了。活用google,SO上这种问题蛮多的
latteczy
2015-07-07 21:19:50 +08:00
@alexapollo 嗯,这段代码效率没提高就是楼上所说的t.join()位置不对。主要原因不在GIL吧
alexapollo
2015-07-07 21:22:53 +08:00
@latteczy 恩,是的
est
2015-07-07 21:27:07 +08:00
GIL 真是个活靶子。
latteczy
2015-07-07 21:39:25 +08:00
@Shazoo 感谢!确实是这样。但是又有个问题是代码改正以后貌似没法统计运行时间了。。
https://gist.github.com/smartczy/35e692064b775dcc3e17#comment-1487649
uniquecolesmith
2015-07-07 21:44:00 +08:00
gevent 用起来
aec4d
2015-07-07 22:06:43 +08:00
这TM关GIL毛事 简直躺枪
要记住 断然给你提GIL的 要么是高手 要么是SB 有GIL还有multiprocessing呢 多线程最需要注意的应该是线程安全
这是threading.join的文档
join([timeout])
Wait until the thread terminates. This blocks the calling thread until the thread whose join() method is called terminates – either normally or through an unhandled exception – or until the optional timeout occurs.

When the timeout argument is present and not None, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). As join() always returns None, you must call isAlive() after join() to decide whether a timeout happened – if the thread is still alive, the join() call timed out.

When the timeout argument is not present or None, the operation will block until the thread terminates.

A thread can be join()ed many times.

join() raises a RuntimeError if an attempt is made to join the current thread as that would cause a deadlock. It is also an error to join() a thread before it has been started and attempts to do so raises the same exception.

看了之后你就发现 在上面加上t.join就和下面遍历的写法实质上是一模一样的.
一般网上很多教程给你加上setDaemon 加上join 你可以试着不加看是什么样的。等你熟悉了之后你就晓得那时候该用这些 哪时候不该用
zhyu
2015-07-07 22:59:29 +08:00
@latteczy
试试不要join
latteczy
2015-07-08 08:27:41 +08:00
@aec4d 多谢大神指点!大神莫激动。。。
fanta
2015-07-08 09:32:06 +08:00
aec4d 说的对,每个连接是0.7s时,问题已不是多线程的问题了, 是网络(服务器链路)问题.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/204035

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX