Runnable、Callable、Future、FutureTask 及应用

一般创建线程只有两种方式,一种是继承Thread,一种是实现Runnable接口。但是这两种创建方式没有返回值,得使用共享变量或者其他通信方式才能得到线程处理完的结果。

一般不提倡使用继承Thread来创建线程方式,因为Java只有单继承,不能继承多个。但是Runnable是接口,所以使用Runnable可以在实现类的同时实现多个接口。

而且在线程池中,如果是使用Runnable来创建线程,那么可以直接将Runnable的实现类作为参数传入给线程池,使用线程池管理线程!

Java1.5之后有了Callable、Future,它们可以提供线程执行完的结果!

接下来简单介绍下Runnable、Callable 、Future、 FutureTask。

Runnable:
Runnable 是一个接口,在run方法中编写要执行的代码,但是没有任务返回接口,并且无法抛出异常。


public class Main {
    static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run()方法正在执行...");
        }
    }

    static class MyRunnable implements Runnable {

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run()方法执行中...");
        }

    }

    public static void main(String[] args) {

        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread();
        thread1.start();

        Thread thread2 = new MyThread();
        thread2.start();
        System.out.println(Thread.currentThread().getName() + " main()方法执行结束");
    }


}

Callable:
Callable也是一个接口,在call方法里编写要执行的代码,返回的是执行的结果。和Runnable相比,它有返回的结果,并且可以抛出异常!

使用Callable+FutureTask获取执行结果:

public class CallableTest {
    static class MyCallable implements Callable<Integer> {

        @Override
        public Integer call() {
            System.out.println(Thread.currentThread().getName() + " call()方法执行中...");
            return 1;
        }

    }

    public static void main(String[] args) {
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyCallable());
        Thread thread = new Thread(futureTask);
        thread.start();

        try {
            Thread.sleep(1000);
            System.out.println("返回结果 " + futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " main()方法执行完成");
    }

}

Future:
Future也是一个接口,它可以对具体的Runnable或者Callable任务进行取消、判断任务是否已取消、查询任务是否完成、获取任务结果。如果是Runnable的话返回的结果是null(下面会剖析为什么Runnable的任务,Future还能返回结果)。接口里面有以下几个方法。注意两个get方法都会阻塞当前调用get的线程,直到返回结果或者超时才会唤醒当前的线程。

    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;  //获取任务结果
    }  

使用Callable+Future获取执行结果:

public class CallableDemo implements Callable<Integer> {  
      
    private int sum;  
    @Override  
    public Integer call() throws Exception {  
        System.out.println("Callable子线程开始计算啦!");  
        Thread.sleep(2000);  
          
        for(int i=0 ;i<5000;i++){  
            sum=sum+i;  
        }  
        System.out.println("Callable子线程计算结束!");  
        return sum;  
    }  
} 
 public class CallableTest {  
          
        public static void main(String[] args) {  
            //创建线程池  
            ExecutorService es = Executors.newSingleThreadExecutor();  
            //创建Callable对象任务  
            CallableDemo calTask=new CallableDemo();  
            //提交任务并获取执行结果  
            Future<Integer> future =es.submit(calTask);  
            //关闭线程池  
            es.shutdown();  
            try {  
                Thread.sleep(2000);  
            System.out.println("主线程在执行其他任务");  
              
            if(future.get()!=null){  
                //输出获取到的结果  
                System.out.println("future.get()-->"+future.get());  
            }else{  
                //输出获取到的结果  
                System.out.println("future.get()未获取到结果");  
            }  
              
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            System.out.println("主线程在执行完成");  
        }  
    }  

FutureTask:
因为Future只是一个接口,所以是无法直接创建对象,因此就有了FutureTask。FutureTask不是接口了,是个class。它实现了RunnableFuture接口

public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> //RunnableFuture接口又继承了Runnable和Future

因此FutureTask可以作为Runnable被线程执行,又可以有Future的操作。它的两个构造器如下:

    public FutureTask(Callable<V> callable) {  
    }  
    public FutureTask(Runnable runnable, V result) {  
    }  

使用Callable+FutureTask获取执行结果的代码在Callable部分已介绍!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值