请教一个有关Python线程的问题
from threading import Thread
class MyThread(Thread):
myname = ""
count = 0
nlist = []
def __init__(self, sname):
Thread.__init__(self)
self.myname = sname
def run(self):
self.count += 1
self.nlist.append(self.name)
print(self.getName(), self.myname, self.count, self.nlist)
if __name__ == "__main__":
th = MyThread("First")
th.start()
th = MyThread("Second")
th.start()
程序输出的是:
Thread-1 First 1 ['First']
Thread-2 Second 1 ['First', 'Second']
从结果看,两个线程貌似没有共享count这个变量(打印出来还是1),但是却共享了nlist这个变量,请高手解答,多谢!
===================================================
另外,我用java做了类似的程序,结果却不一样:
import java.util.ArrayList;
import java.util.List;
public class TestThread
{
public static void main(String[] args)
{
MyThread t = new MyThread("First");
t.start();
t = new MyThread("Second");
t.start();
}
}
class MyThread extends Thread
{
private String name = "";
private int count = 0;
private List<Object> mylist = new ArrayList<Object>();
public MyThread()
{
}
public MyThread(String name)
{
this.name = name;
}
@Override
public void run()
{
count++;
mylist.add(this.name);
System.out.printf("%s__%d__%s\n", this.getName(), this.count, this.mylist.toString());
}
}
程序输出:
Thread-1__1__[Second]
Thread-0__1__[First]
在这里,java线程貌似没有像Python线程一样共享那个mylist变量,请高手指教,多谢!
[解决办法]
这个问题和线程无关。主要是python的类变量的访问方式。个人觉得这点python不是很严谨。
如果你通过
class XXX:
count = 0
定义变量,这个变量属于类的静态变量(我是这么称呼的)
但一个对象也可以拥有同名的成员变量。
比如self.count,首先它会找这个对象有没有count这个成员,如果没有,再看这个类别有没有这个成员。
在你的代码中,
self.count+=1
实际上被翻译成了这样的句子,你可以这样理解
self.count=self.count+1
当解释器求右边等式的值的时候,这时对象本身还没有count这个成员。
所以被解释成
self.count=MyThread.count+1
self.count=0+1
这时候,self.count被赋值了,因此对象增加了一个count的成员变量
如果你希望存储的是类的静态变量,应该用
MyThread.count+=1
就对了
如果你没对一个和静态变量同名的变量进行过赋值,那么通过self.xxx访问的就是该类的静态变量。
因此你的第二个问题,为什么nlist会共享,因为nlist没被赋值,只是在原有对象做了操作
如果改成
self.nlist = [self.name]
它的效果就和count一样了。
为了避免误解增加可读性,建议代码写成这样
class MyThread(Thread):
myname = ""
count = 0
nlist = []
def __init__(self, sname):
Thread.__init__(self)
self.myname = sname
def run(self):
MyThread.count += 1
MyThread.nlist.append(self.name)
print(self.getName(), self.myname, MyThread.count, MyThread.nlist)
用明确的类名代替暧昧不清的self