线程getName()返回错误的名称

lui*_*7up 5 java multithreading thread-safety

好吧,我知道很难理解线程是如何工作的,但是直到有人帮助我理解我会相信它是一个bug :)

在我的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");
    [...]
Run Code Online (Sandbox Code Playgroud)

然后在我的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){
            [...]
Run Code Online (Sandbox Code Playgroud)

当我编译并运行此代码时,我得到:

2个主题的屏幕截图...

所以,我的问题是为什么这两个线程都返回相同的名称currentThread().getName()?当它们被创建时,它们被分配了名称,threadX.setName("XXX")并且通过调用启动了那些可运行的threadX.start()...有人可以澄清一下这个吗?

编辑:我接受了正确的答案,因为将stRunnable更改为stRunnable2的行为是预期的.现在真正的问题是为什么会发生这种情况.我创建两个线程并分别启动它们.如何运行run()方法(在创建线程时调用一次)返回错误的名称?

hoa*_*oaz 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)
Run Code Online (Sandbox Code Playgroud)

  • 最后一个合理的诊断.+1 (2认同)

NPE*_*NPE 5

您使用相同的runnable创建两个线程:

Thread throwingThread = new Thread(stRunnable);
Thread throwingThread2 = new Thread(stRunnable);
                                    ^^^^^^^^^^ stRunnable2?
Run Code Online (Sandbox Code Playgroud)

将线程名称存储在Runnable对象的实例变量中.由于该对象由两个线程共享,因此要执行的第二个线程将name = Thread.currentThread().getName()使用自己的名称覆盖第一个线程的名称.