如何启动匿名线程类

65

我有以下的代码片段:

public class A {
    public static void main(String[] arg) {
        new Thread() {
            public void run() {
                System.out.println("blah");
            }
        };
    }
}

在这里,我如何调用线程的start()方法而不创建线程类的实例?


2
Java 遵循 里氏替换原则,所以您创建的匿名类的实例也是 Thread 的实例。 - Pacerier
9个回答

150

您已经创建了Thread类的实例 - 只是没有使用它。您可以甚至不使用本地变量调用start()

new Thread()
{
    public void run() {
        System.out.println("blah");
    }
}.start();

...但是个人建议将其分配给本地变量,进行其他任何操作(例如设置名称等),然后启动它:

Thread t = new Thread() {
    public void run() {
        System.out.println("blah");
    }
};
t.start();

2
以上两者有什么区别?创建一个实现者并将其放置在线程构造函数中:new Thread(new Runnable() {public void run(){}})。 - Malwaregeek
2
@Malwaregeek:在一个情况下,实现是Thread的子类,而在另一个情况下,则是Runnable的匿名类实现。它们是不同的,但通常差异是无关紧要的。 - Jon Skeet
@Malwaregeek 尽管实现 Runnable 接口可能稍微更受欢迎。请参见 Jon 在此处的答案 - MC Emperor
@JonSkeet 在重写的 run 方法中引用创建线程类的对象,这是正确的方法吗? - uhs
@uhs:没问题 - 你有具体的顾虑吗? - Jon Skeet

15

由于匿名类扩展了给定的类,因此您可以将它们存储在变量中。

例如:

Thread t = new Thread()
{
    public void run() {
        System.out.println("blah");
    }
};
t.start();

或者,您可以直接在所创建的对象上调用start方法。

new Thread()
{
    public void run() {
        System.out.println("blah");
    }
}.start();
// similar to new Thread().start();

个人建议始终创建一个匿名的Runnable实例,而不是Thread实例。因为如果您意外地错误地获取方法签名,编译器会发出警告(对于匿名类,它将无论如何发出警告,因为匿名类不能定义新的非私有方法)。

例如:

new Thread(new Runnable()
{
    @Override
    public void run() {
        System.out.println("blah");
    }
}).start();

你也可以使用lambda表达式new Thread(() -> System.out.println("blah")) - MC Emperor

6

我不确定您的意思,但是您可以尝试以下方法:

new Thread() {
    public void run() {
        System.out.println("blah");
    }
}.start();

注意在匿名类的末尾有start()方法。您创建了线程对象,但需要启动它才能获得另一个运行中的线程。

比创建匿名Thread类更好的方法是创建匿名Runnable类:

new Thread(new Runnable() {
    public void run() {
        System.out.println("blah");
    }
}).start();

与其在Thread中覆盖run()方法,不如将一个目标Runnable注入到新线程中运行。这是一种更好的模式。


4

新增:现在您可以使用Lambda表达式来简化语法。要求:Java 8或以上版本。

public class A {
    public static void main(String[] arg)
    {
        Thread th = new Thread(() -> {System.out.println("blah");});
        th.start();
    }
}

4

只需调用 start() 函数即可。

new Thread()
{
    public void run() {
        System.out.println("blah");
    }
}.start();

3
整个new表达式是一个对象引用,因此可以在其上调用方法:
public class A {
    public static void main(String[] arg)
    {
        new Thread()
        {
            public void run() {
                System.out.println("blah");
            }
        }.start();
    }
}

1

把这个留在这里以备将来参考,但它也是一个答案。

new Thread(() -> whatever()).start();

你能解释一下这里发生了什么吗?这是Lambda还是某种隐式创建的Runnable的->run? - Mat90

1
创建扩展Thread类的匿名类时,可以使用另一个方便的技巧,而不仅仅是将Runnable实例或lambda传递给Thread类的构造函数:
  // This also starts the new thread when instantiating the Anonymous class
  // By invoking "this.start()" in a instance initializer block of the Anonymous Thread.
  // Note: We can also override the run from the Thread class itself instead if providing external runnable just in case.
  Thread t = new Thread(()->{}){{start();}};
  
  Runnable r1 = ()->{}; // Runnable Functional Interface lambda format  
  Thread t1 = new Thread(r1){{start();}};

  // Anonymous class which implements Runnable interface
  Runnable r2 = new Runnable(){
    @Override
    public void run(){
      //do some work 
    }
  }
  Thread t2 = new Thread(r2){{start();}};

  // Anonymous class which extends Thread class
  Thread t3 = new Thread(){
    {
       start();
    }
    @Override
    public void run(){
      //do some useful work
    }
  }
  
  class ExtendedThread extends Thread{
    ExtendedThread(){this(null);}
    ExtendedThread(Runnable runnable){
       super(runnable);
       start();
    }
    @Override
    public void run(){
      super.run();
      //do some more useful work always even if there was no runnable was passed via constructor
    } 
  }
  
  Thread t3 = new Thread();

0
我很惊讶在这个问题的答案中没有看到任何关于Java Executor框架的提及。Executor框架的主要卖点之一是,您不必处理低级线程。相反,您正在处理ExecutorServices的更高级抽象层次。因此,只需执行包装Runnable的执行器,而不是手动启动线程。使用单个线程执行器,您创建的Runnable实例将在内部被包装并执行为线程。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
// ...

ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
try {
  threadExecutor.execute(
    new Runnable() {
      @Override
      public void run() {
        System.out.println("blah");
      }
    }
  );
} finally {
    threadExecutor.shutdownNow();
}

为了方便起见,请查看JDoodle上的代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接