Callable和Future接口

前面我们介绍过使用Runnable接口创建线程,但它有一个缺点,没有提供一个接收返回值的地方。为了实现该功能,JDK5引入了Callable接口,配合Future接口能够实现获取子线程返回值的目的。

Callable和Future

我们先来看一下这两个接口声明的方法。

Callable.java

package java.util.concurrent;

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

Callable接口包含call()方法,和Runnable不同的是它具备一个返回值。

Future.java

package java.util.concurrent;

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

前面call()方法的返回值为了能被主线程读取到,就必须有一个对象来控制和接收返回值,Future就是为这个目的设计的。cancel()方法可以停止子线程任务,如果子线程未启动则直接停止,如果子线程已启动则当mayInterruptIfRunning参数为true时将其interrupt;isDone()方法可以获取任务是否完成;get()方法用于获取任务返回的结果,如果无结果则阻塞等待。

FutureTask

实际上我们没必要直接使用前面的Future接口,JDK提供了FutureTask类实现了FutureRunnable接口,这里我们介绍其用法。

package com.gacfox.demo;

import java.util.concurrent.Callable;

public class MyThread implements Callable<String> {

    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        return "执行成功";
    }
}
package com.gacfox.demo;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> myThread = new MyThread();
        FutureTask<String> futureTask = new FutureTask<>(myThread);
        new Thread(futureTask).start();
        String s= futureTask.get();
        System.out.println(s);
    }
}

代码中我们的MyThread实现了Callable接口,并返回了一个字符串。main()方法中,我们创建了一个FutureTask对象,然后将其传给Thread类并启动线程,最后我们阻塞等待线程返回值,当线程执行完毕后futureTask.get()取的返回值,输出后程序结束。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap