多线程 Callable Runnable 与Future

本文详细对比了Callable与Runnable接口的使用方法及区别,并介绍了Future接口的功能及其子类FutureTask的具体用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文按:
1. Callable 与Runnable的使用
2. Callable 与Runnable的区别
3. Future的使用
4. FutureTask的使用

1. Callable 与Runnable的使用

Callable经常与ExecutorService配合使用,用于提交带有返回值的任务; Runnable可以与thread pool配合使用也可以单独使用。具体的使用方法如下:

public class RunnableAndCallable {

    static ExecutorService executor = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        //Runnable
        executor.execute(new RunnableTask());
        executor.submit(new RunnableTask());

        //Callable & Future
        Future<String> future = executor.submit(new CallableTask());
        try {
            System.out.println((String) future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        //FutureTask & Callable
        FutureTask<String> futureTask = new FutureTask<String>(new CallableTask());
        try {
            //任务执行
            futureTask.run();
            String s = (String)futureTask.get();
            System.out.println("FutureTask " + s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
//否则线程不会退出
 executor.shutdown();
    }

}

//返回参数为空
//使用execute() 提交任务
class RunnableTask implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " start runnable");
    }
}

//是一个泛型接口,具有返回参数
//使用submit() 提交任务
class CallableTask implements Callable<String>{

    @Override
    public String call() throws Exception {
        return "here is callable test";
    }
}

2. Callable 与Runnable的区别

(1)Runnable 接口是自java 1.0就有的, Callable接口是java1.5以后加入的特性
(2)Callable 接口使用call()方法执行task;Runnable接口使用run()执行task
(3)run()方法没有返回值,Callable接口是一个泛型参数接口,具有返回值
(4)Callable定义的Task只能用submit() 方法添加到任务队列; Runnable定义的接口既可以使用submit()也可以使用execute()提交到任务队列
(5)如果使用invokeAll()一次提交多个任务只能使用Callable实现的任务

3. Future的使用

Future接口的代码如下:

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;
}
  • cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
  • isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
  • isDone方法表示任务是否已经完成,若任务完成,则返回true;
  • get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
  • get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。

也就是说Future提供了三种功能:

  1)判断任务是否完成;

  2)能够中断任务;

  3)能够获取任务执行结果。

  因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。
  
4. FutureTask 的使用

FutureTask类:

public class FutureTask<V> implements RunnableFuture<V>

RunnableFuture 接口:

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

参考:http://www.cnblogs.com/dolphin0520/p/3949310.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值