好的,我知道很难理解线程是如何工作的,但是在有人帮助我理解之前我会相信这是一个错误:)
在我的Main类及其main()方法中,我有:
public static void main(String args[]){
StoneBucket stoneBucket = new StoneBucket();
StonePutter spRunnable = new StonePutter(stoneBucket);
StoneThrower stRunnable = new StoneThrower(stoneBucket);
StoneThrower stRunnable2 = new StoneThrower(stoneBucket);
//Create the Threads that will take the Runnables as arguments
Thread puttingThread = new Thread(spRunnable);
Thread throwingThread = new Thread(stRunnable);
Thread throwingThread2 = new Thread(stRunnable);
puttingThread.setName("Putter");
throwingThread.setName("Thrower 1");
throwingThread2.setName("Thrower 2");
[...]
然后在我的StoneThrower课程中我有
public class StoneThrower implements Runnable{
private StoneBucket sb;
private String name;
public StoneThrower(StoneBucket _sb){
this.sb = _sb;
}
public void run(){
name = Thread.currentThread().getName();
System.out.println("T::"+name+" started...");
int count = 0;
while(true){
[...]
当我编译并运行此代码时,我得到了:
所以,我的问题是为什么这两个线程都为currentThread().getName()
返回相同的名称?
在创建它们时,它们通过threadX.setName("XXX")
分配了名称,并通过调用threadX.start()
启动了那些可运行的...
有人可以请你澄清一下吗?
编辑:我接受了正确的答案,因为将stRunnable更改为stRunnable2的行为与预期一致。现在真正的问题是为什么会发生这种情况。我创建两个线程并分别启动它们。 run()方法(在创建线程时调用一次)返回错误的名称是怎么回事?
答案 0 :(得分:9)
这是因为您将线程名称存储在name
的实例变量StoneThrower
中。由于并发性,第二个线程会覆盖第一个线程刚刚设置的name
的值,并且它们都输出相同的值。
以下是您的情景:
1. Thread1#start
2. Thread2#start
3. Thread1#runnable#run -> runnable.name = 'Thrower 1'
4. Thread2#runnable#run -> runnable.name = 'Thrower 2' // overrides
5. Thread1#runnable#run -> System.out.println(runnable.name)
6. Thread2#runnable#run -> System.out.println(runnable.name)
答案 1 :(得分:5)
您使用相同的runnable创建两个线程:
Thread throwingThread = new Thread(stRunnable);
Thread throwingThread2 = new Thread(stRunnable);
^^^^^^^^^^ stRunnable2?
将线程名称存储在Runnable
对象的实例变量中。由于该对象由两个线程共享,因此执行name = Thread.currentThread().getName()
的第二个线程会用自己的名称覆盖第一个线程的名称。