JAVA线程构造和创建

88 阅读2分钟

线程构造和创建

实现 Runnable 接口创建多线程

  • 采用 Runnable 接口的方式创建的多个线程可以共享同一个 target 对象的实例变量
  • void run():使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法
// 定义 Runnable 接口的实现类
public class MyRunnable implements Runnable {
    // 重写 Runnable 接口中的 run() 方法,线程执行体
    public void run() {
    }
}
public class Demo {
    public static void main(String[] args) {                
        Runnable target = new MyRunnable(); // 创建 Runnable 实现类的对象 target
        Thread t = new Thread(target, "线程名"); // 将 target 作为运行目标来创建创建 Thread 类的对象
        t.start();; // 调用线程对象的 start() 方法来启动该线程
    }
}
// 使用匿名内部类的方式创建
new Thread(new Runnable() {
    public void run() {
    }
}).start();

使用 Callable 和 FutureTask 创建线程

Callable 接口

  • Callable 接口提供了一个 call() 方法(可以有返回值,可以声明抛出异常)可以作为线程执行体,Callable 接口里的泛型形参类型与 call() 方法返回值类型相同
  • V call():计算结果,如果无法计算结果,则抛出一个异常

Future 接口

  • Future 接口代表 Callable 接口里 call() 方法的返回值,表示异步计算的结果
  • Future 接口的常用方法V get():返回 Callable 任务里 call() 方法的返回值,如果计算抛出异常将会抛出 ExecutionException 异常,如果当前的线程在等待时被中断将会抛出 InterruptedException 异常(调用该方法将导致程序阻塞,必须等到子线程结束后才会得到返回值)V get(long timeout, TimeUnit unit):返回 Callable 任务里 call() 方法的返回值,该方法让程序最多阻塞 timeout 和 unit 指定的时间,如果经过指定时间后 Callable 任务依然没有返回值,将会抛出 TimeoutException 异常boolean cancel(boolean maylnterruptlfRunning):试图取消该 Future 里关联的 Callable 任务boolean isCancelled():如果在 Callable 任务正常完成前被取消,则返回 trueboolean isDone():如果 Callable 任务已完成,则返回 true

FutureTask 类

  • FutureTask 实现类实现了 RunnableFuture 接口(RunnableFuture 接口继承了 Runnable 接口和Future 接口)
  • 构造器:FutureTask(Callable callable)、FutureTask(Runnable runnable, V result)(指定成功完成时 get 返回给定的结果为 result)
// 使用 Lambda 表达式创建 Callable<V> 接口的实现类,并实现 Call() 方法
// 使用 FutureTask 来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值
FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>) () -> {
    // call() 方法可以有返回值
    return 100;
});
// 将 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程
new Thread(task, "线程名").start();
try {
    // 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值,在最多等待 1 秒之后退出
    System.out.println("子线程的返回值:" + task.get(1, TimeUnit.SECONDS));
} catch (Exception e) {
    e.printStackTrace();
}