创建新线程
运行一个Java 程序的实质就是启动一个 JVM 进程,然后,JVM 启动主线程来执行main
方法。在 main 方法中,我们又可以启动其他线程。
Thread 类和 Runnable 接口
在 Java 中创建一个线程就是创建一个Thread类
(或其子类)的实例(对象),然后调用它的start()
方法启动。
public class Main {
public static void main(String[] args) {
Thread t = new Thread();
t.start();
// 注意:这个线程启动后什么都没做
}
}
注意:不可多次调用 start() 方法。在第一次调用 start() 方法后,再次调用 start() 方法会抛出异常。
每个线程都有其要执行的任务,我们希望线程能执行指定的任务代码。为此,Java 提供了两种方法。
继承 Thread 类
定义 Thread 类的子类,在该子类中覆盖(重写)run()
方法。
class HelloWorldThread extends Thread {
@Override
public void run() {
System.out.println("Hello, world!");
}
}
public class Main {
public static void main(String[] args) {
Thread t = new HelloWorldThread();
t.start();
// 控制台输出:Hello, world!
}
}
在程序里调用了 start() 方法后,JVM 会为我们创建一个线程,然后等到这个线程第一次得到时间片时 JVM 再执行 run() 方法。
实现 Runnable 接口
创建 Thread 实例时,传入一个Runnable接口
实现类的实例。
class HelloWorldTask implements Runnable {
@Override
public void run() {
System.out.println("Hello, world!");
}
}
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new HelloWorldTask());
t.start();
// 控制台输出:Hello, world!
}
}
在 JDK1.8 及以上版本中,注意到 Runnable接口 是一个函数式接口。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
因此,我们可以使用 JDK1.8 引入的lambda表达式
进一步简写。
public class Main {
public static void main(String[] args) {
Thread t = new Thread(() -> System.out.println("Hello, world!"));
t.start();
// 控制台输出:Hello, world!
}
}
两种方式的区别(以面向对象的角度)
第 1 种创建方式(创建 Thread 类的子类)是一种基于继承方式
第 2 种创建方式(以 Runnable 接口为构造器参数直接通过 new 创建 Thread 实例)是一种基于组合 的方式。
组合对继承来说,其类和类之间的耦合性
更低,因此它也更加灵活。一般我们认为组合是优先选用的方式。