【问题标题】:thread in python vs C# vs Rubypython vs C# vs Ruby中的线程
【发布时间】:2011-10-13 09:55:44
【问题描述】:

我想我找到了一些 C# 和 Ruby 可以做但 Python 做不到的事情

在 C# 中:

for (var i = 0; i < 100; i++)
    new Thread(() => { Console.Write(i+" "); }).Start();
Console.ReadLine();

在 Ruby 中:

for i in 0...100
    Thread.start{
        print i + ''
    }
end

gets

有什么想法吗?你能用python重写上面的代码吗?输出应该类似于 C# 和 Ruby:有重复的数字

编辑
输出为 100 次打印,重复数字。如果你定义一个类或一个新方法,你只会得到100次打印,没有重复的数字。我知道得到重复的数字是没有意义的,我只想用python来达到和C#和ruby一样的效果。

C# 的示例输出:

3 3 3 3 5 7 8 8 10 10 12 12 13 14 17 17 17 18 20 20 22 23 24 24 25 28 28 29 29 3
1 31 33 33 34 36 38 38 38 41 41 41 42 44 45 45 46 49 49 50 50 52 52 55 56 56 56
58 59 59 60 61 64 64 64 66 66 67 68 69 72 72 72 73 74 76 76 78 78 81 81 82 83 84
 84 86 86 87 89 89 90 93 94 94 95 95 97 97 99 99 100

Ruby 的示例输出:

99999999999999999999999999999999999999999999999999999999999999999999999999999999
99999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999

为什么我想要重复的数字:
C# 和 ruby​​ 代码的输出有重复的数字。那是因为,主线程正在改变 i 的值,所以一些子线程可能会打印相同的数字。 主线程和子线程引用同一个变量 i。 有时这很有用:主线程更改变量,子线程都得到更新的变量。 但是我们如何在 Python 中做到这一点呢?

【问题讨论】:

  • 扩展线程。线程听起来比其他的设计模式更好。它封装得很好,而且非常干净。
  • 重复数字是什么意思?你的意思是你得到“1” 100 次,然后是“2” 100 次,等等还是什么?
  • @agf,我将 WriteLine(i) 更改为 Write(i+" ")。 C# 的示例输出: 3 3 3 3 5 7 8 8 10 10 12 12 13 14 17 17 17 18 20 20 22 23 24 24 25 28 28 29 29 3 1 31 33 33 34 36 38 38 38 41 41 41 4 2 45 45 46 49 49 50 50 52 52 55 56 56 52 52 59 56 56 56 52 52 59 56 68 69 72 72 72 73 74 76 76 72 78 81 81 82 83 84 84 86 86 87 89 89 90 93 94 94 95 95 97 97 99 99 100。

标签: c# python ruby multithreading closures


【解决方案1】:

再次编辑:

我想我找到了一些 C# 和 Ruby 可以做但 Python 做不到的事情

不,这有重复的数字,看起来非常像您的 Ruby/C# 代码。

import threading
import sys

for i in xrange(100):
    threading.Thread(target=lambda: sys.stdout.write('{0}\n'.format(i))).start()

-

14
15
17
17
18
19
20

【讨论】:

  • 我觉得你的回答是对的。只是不那么pythonic。是的,我知道 pythonic 方式不能产生重复的数字,所以你必须这样做。谢谢!
【解决方案2】:

如果您希望不同的线程有时会看到相同的 i 值,那么您需要传入一个可变对象并对其进行变异:

import threading

def action(arg):
    print arg[0],

mutable = [0]
for i in range(100):
    mutable[0] = i
    threading.Thread(target=action, args=(mutable,)).start()

这与您是否为线程定义单独的类无关,这完全取决于您如何在线程之间共享值。一个全局变量也会以同样的方式搞乱你的线程。

样本输出:

0 1 2 3 5 5 6 8 9 9 11 11 12 1314 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 3
0 31 32 33 34 35 36 37 39 39 40 41 43 44 44 45 46 47 48 49 50 51 53 53 54 55 56
5758 59 60 61 62 64 65 6666 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 8
4 85 86 87 89 90 90 92 93 93 94 95 96 9898 99

【讨论】:

  • 有时不是“乱七八糟”,而是有用的。如果真的想要他们共享相同的变量
  • 在 Python 中你只需要共享同一个对象而不是共享同一个变量。这在其他语言中通常也是如此,因为您想确保对值的访问有适当的锁定:Python 的 GIL 确保您不必担心简单对象的锁定,但您仍然应该担心任何可变的内容。
【解决方案3】:

在 Python 中:

import threading

def action(arg):
    print arg

for i in range(100):
    threading.Thread(target=action, args=(i,)).start()

【讨论】:

  • 当然,没有新类,但有新方法。好多了。
  • @Tyler:您的意思是扩展threading.Thread 并重新定义run 方法,当然可以,但取决于用例,例如。在这个例子中,这样做会有点过头了。
  • 是的,一门课太熟练了。但我们最好也省略这种方法。因为有些事情确实很重要。运行 C# 和 ruby​​ 代码,你会得到很多重复的打印。那是因为他们使用内联闭包而不是新方法。
【解决方案4】:

其实你可以:

>>> import threading
>>> def target():
...     print 123
...
>>> threading.Thread(target=target).start()
123

您的示例如下所示:

>>> def target(i):
...     print i
...
>>> for i in xrange(100):
...     threading.Thread(target=target, args=(i,)).start()
...
0
1
2
3
<and so on>

【讨论】:

  • 不是对 ruby​​ 或 C# 代码的重写。但无论如何,我知道不用在 Python 中定义新类就可以使用多线程。谢谢。
  • 所有线程会并行写入stdout,输出会乱码。如果您希望输出干净,则需要锁定打印,但即使这样,顺序也是不可预测的。
  • 我不知道你所说的“不同的输出”是什么意思,但我想指出,如果你真的想要的话,你甚至可以像在 Ruby 和 C# 中那样内联声明它(在 Python 2.6 或更高版本中)使用from __future__ import print_function 或在 Python 3 中):threading.Thread(target=(lambda i: print(i)), args=(i,)).start()
  • @agf,我不知道它可以作为内联完成。据说python中的lambda必须是单个表达式(不是语句)。
  • 没错。 print 是我描述的情况下的一个函数,所以print(i) 是一个表达式。在普通的 Python 2 中,print 是一个语句,这是不可能的。我仍然认为内联是一件“坏事”,我只是想指出,如果你想做的事情真的足够简单以至于它可能有意义的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-06
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
  • 2014-08-30
相关资源
最近更新 更多