【问题标题】:Unable to set name of a thread in java无法在java中设置线程的名称
【发布时间】:2015-12-22 06:54:45
【问题描述】:

我正在学习 Java 中的 Thread 并且有一个像这样的小程序。我创建一个线程并使用它来创建另一个线程。但是我不能更改第二个线程的名称。谁能解释为什么会这样?另外,Thread.sleep(100) 表示主线程将休眠 100 毫秒是否正确。谢谢。

class Thread1 extends Thread{
   public void run() {      
      for(int i=0;i<5;i++){
        System.out.println(getName()+" is running. Time is "+i);
      }
   }
}

public class Program{   
    public static void main(String[] args) throws InterruptedException {        
       Thread t1 = new Thread1();
       t1.setName("Thread 1");
       Thread t2 = new Thread(t1);
       t2.setName("Thread 2");
       t1.start();
       Thread.sleep(100);       
       t2.start();      
    }       
}

这个程序的结果是:

Thread 1 is running. Time is 0
Thread 1 is running. Time is 1
Thread 1 is running. Time is 0
Thread 1 is running. Time is 1

编辑:如果我将 getName() 更改为 Thread.currentThread().getName() 那么一切都按预期工作。它们之间有什么区别?

【问题讨论】:

    标签: java multithreading


    【解决方案1】:
       Thread t1 = new Thread1();
       t1.setName("Thread 1");
       Thread t2 = new Thread(t1);   <--- See this.
    

    您正在将之前创建的线程实例 (t1) 传递给下一个线程实例 (t2)。这就是为什么会出现同名的原因。

    应该是这样的:

       Thread t2 = new Thread1();
       t2.setName("Thread 2");
    

    输出:

    Thread 1 is running. Time is 0
    Thread 1 is running. Time is 1
    Thread 1 is running. Time is 2
    Thread 1 is running. Time is 3
    Thread 1 is running. Time is 4
    Thread 2 is running. Time is 0
    Thread 2 is running. Time is 1
    Thread 2 is running. Time is 2
    Thread 2 is running. Time is 3
    Thread 2 is running. Time is 4
    

    另外,Thread.sleep(100) 表示主线程将休眠 100 毫秒是否正确。

    是的。那是对的。 Thread.sleep(milliseconds) 以毫秒为单位获取参数。


    当您在创建 Thread 对象时传递 Thread 实例时。这个新线程将使用传递的实例来执行(作为 Runnable 实例)。这就是为什么您会得到Thread 1 以及正在运行的线程不同的地方,新创建的线程实例。所以 Thread.currentThread().getName() 会给你你设置的名字。

    public class Thread implements Runnable {
    ....
    ....
    
    /* What will be run. */
    private Runnable target;       // <-- Runnable is defined here for the thread.
    
    
    public Thread(Runnable target) {  //<-- constructor you are calling.
        init(null, target, "Thread-" + nextThreadNum(), 0); //<-- internal init call.
    }
    
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null);  //<-- internal init call.
    }
    
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
    .....
    .....
    this.target = target;     // <-- Set the Runnable for the thread.
    .....
    }
    ....
    ....
    }
    

    【讨论】:

    • 谢谢@YoungHobbit。如果线程 2 是从线程 1 创建的,那是否意味着线程 1 和线程 2 基本相同?我刚刚更新了我的问题。当我将方法从 getName() 更改为 Thread.currentThread().getName() 时,一切都按预期工作。
    • 如果线程 2 是从 t1 创建的,这意味着线程 2 将作为单独的线程运行,但会执行 t1 中的任何内容。因此,当它执行getName() 时,它会从t1 获取名称。它仍然是一个单独的线程,但执行的代码与另一个线程相同。
    • @Steven:线程扩展了 Runnable。当您将 t1 作为参数传递给 t2 时,t1 被 t2 视为 Runnable,它作为 Thread 与任何东西都无关,您只是在混淆自己。
    • @Steven 我已经添加了内部方法调用,这是如何发生的并运行线程。希望这将为您消除困惑。您还可以查看Thread 类的代码。 Erick G. Hagstrom和Nathan Hughes提供的解释是正确的。
    【解决方案2】:

    当我们创建线程对象时,JVM 会为该线程指定默认名称。 JVM 分配的默认线程名称类似于 - Thread-(int Value),例如 Thread-0、Thread-1 等。


    如果我们想为线程使用我们自己的名称而不是使用默认名称,那么我们可以通过传递我们自己的名称作为参数来使用 Thread 类的构造函数。 class MyThread extends Thread{ .. MyThread(String tname) { super(tname); } } .. MyThread th=new MyThread("My-Thread");


    如果我们想在创建具有某个名称的线程对象后更改线程的名称,那么我们可以使用方法 - public final void setName(String name)

    【讨论】:

      猜你喜欢
      • 2012-07-27
      • 1970-01-01
      • 2018-08-04
      • 2011-01-23
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      相关资源
      最近更新 更多