Java多线程(二):创建新线程

111 阅读2分钟

创建新线程

运行一个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 实例)是一种基于组合 的方式。

组合对继承来说,其类和类之间的耦合性更低,因此它也更加灵活。一般我们认为组合是优先选用的方式。