“我应该实现Runnable还是扩展Thread类?”这是一个很常见的问题。

在本文中,我们将看到哪种方法在实践中更有意义以及为什么。

使用Thread

我们首先定义一个扩展线程Thread的SimpleThread类:

public class SimpleThread extends Thread {

    private String message;

    // standard logger, constructor

    @Override
    public void run() {
        log.info(message);
    }
}

让我们看看如何运行这种类型的线程:

@Test
public void givenAThread_whenRunIt_thenResult()
  throws Exception {
 
    Thread thread = new SimpleThread(
      "SimpleThread executed using Thread");
    thread.start();
    thread.join();
}

我们还可以使用ExecutorService来执行线程:

@Test
public void givenAThread_whenSubmitToES_thenResult()
  throws Exception {
    
    executorService.submit(new SimpleThread(
      "SimpleThread executed using ExecutorService")).get();
}

在单独的线程中运行单个日志操作需要大量代码。

此外,请注意SimpleThread不能扩展任何其他类,因为Java不支持多重继承。

实现Runnable

现在,让我们创建一个实现java.lang.Runnable接口:

class SimpleRunnable implements Runnable {
	
    private String message;
	
    // standard logger, constructor
    
    @Override
    public void run() {
        log.info(message);
    }
}

上面的SimpleRunnable只是一个我们希望在单独线程中运行的任务。

我们可以使用各种方法来运行它;其中之一是使用Thread类:

@Test
public void givenRunnable_whenRunIt_thenResult()
 throws Exception {
    Thread thread = new Thread(new SimpleRunnable(
      "SimpleRunnable executed using Thread"));
    thread.start();
    thread.join();
}

我们甚至可以使用ExecutorService

@Test
public void givenARunnable_whenSubmitToES_thenResult()
 throws Exception {
    
    executorService.submit(new SimpleRunnable(
      "SimpleRunnable executed using ExecutorService")).get();
}

由于我们现在正在实现一个接口,如果需要,我们可以自由扩展另一个基类。

从Java 8开始,任何公开单个抽象方法的接口都被视为函数接口,这使其成为有效的lambda表达式目标。

我们可以使用lambda表达式重写上述可运行代码:

@Test
public void givenARunnableLambda_whenSubmitToES_thenResult() 
  throws Exception {
    
    executorService.submit(
      () -> log.info("Lambda runnable executed!"));
}

Runnable还是Thread?

简单地说,我们通常鼓励使用Runnable

  • 在扩展Thread类时,我们没有重写它的任何方法。相反,我们重写了Runnable方法(线程恰好实现了该方法)。这明显违反了 IS-A 线程原则
  • 创建Runnable的实现并将其传递给Thread类利用组合而不是继承,这更灵活
  • 在扩展Thread类之后,我们不能扩展任何其他类
  • 从Java 8开始,Runnables可以表示为lambda表达式

结论

实现Runnable通常比扩展Thread类更好。


免责声明:本文系转载,版权归原作者所有;旨在传递信息,不代表一休教程网的观点和立场。