线程:基础知识

使用线程

有三种使用线程的方法:

  • 实现 Runnable 接口;
  • 实现 Callable 接口;
  • 继承 Thread 类。

实现 RunnableCallable 接口的类只能当做一个可以在线程中运行的任务,不是真正意义上的线程,因此最后还需要通过 Thread 来调用。可以理解为任务是通过线程驱动从而执行的。

实现 Runnable 接口

需要实现接口中的 run() 方法。

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // ...
    }
}Copy to clipboardErrorCopied

通过 Runnable 实例创建一个 Thread 实例,然后调用 Thread 实例的 start() 方法来启动线程。

public static void main(String[] args) {
    MyRunnable instance = new MyRunnable();
    Thread thread = new Thread(instance);
    thread.start();
}

实现 Callable 接口

与 Runnable 相比,Callable 可以有返回值,返回值通过 FutureTask 进行封装。

public class MyCallable implements Callable<Integer> {
    public Integer call() {
        return 123;
    }
}

通过 Callable实例创建一个 FutureTask 实例,通过 FutureTask 实例创建 Thread 实例,然后调用 Thread 实例的 start() 方法来启动线程。

public static void main(String[] args) throws ExecutionException, InterruptedException {
    MyCallable mc = new MyCallable();
    FutureTask<Integer> ft = new FutureTask<>(mc);
    Thread thread = new Thread(ft);
    thread.start();
    System.out.println(ft.get());
}

继承 Thread 类

同样也是需要实现 run() 方法,因为 Thread 类也实现了 Runable 接口。

当调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。

public class MyThread extends Thread {
    public void run() {
        // ...
    }
}
public static void main(String[] args) {
    MyThread mt = new MyThread();
    mt.start();
}

实现接口 VS 继承 Thread

一般而言,推荐实现接口,主要是由于大多数情况下,人们并不会特别去关注线程的行为,也不会去改写Thread已有的行为或方法,仅仅是期望执行任务而已。
因此,使用接口的方式能避免引入一些并不需要的东西,同时也不会影响继承其他类,并使程序更加灵活。

Tips:

  1. Runnable 与 Thread 不是对等的概念
    Thinking in Java 中,作者吐槽过 Runnable 的命名,称其叫做 Task 更为合理。
    在 Java 中,Runnable 只是一段用于描述任务的代码段而已,是静态的概念,需要通过线程来执行。而 Thread 更像是一个活体,自身就具有很多行为,能够用来执行任务。

  2. 仅仅当你确实想要重写(override)一些已有行为时,才使用继承,否则请使用接口。

发布了39 篇原创文章 · 获赞 83 · 访问量 5530

猜你喜欢

转载自blog.csdn.net/siriusol/article/details/104706745