Callable的Future模式

  线程实现方式:
                1.继承Thread类
                2.实现Runnable接口
                3.线程池
                4.Callable

  无论使用继承Thread类还是实现Runnable接口,还是使用线程池都没有办法解决2个问题
                1.线程执行没有返回值结果
                2.线程执行没有办法抛出异常,只能自己通过try-catch解决

 

  Callable和Runnable类似,在JUC包下,主要区别在于Callable中的call方法可以带返回值并且可以抛出异常
       如果需要执行Callable,需要Future实现类的支持,能够接受返回值结果,FutureTask是Future实现类

 

  调用Callable的第一种实现方案:

                public class MyCallable implements Callable<String> {
                    @Override
                    public String call() throws Exception {
                        System.out.println("Callable接口中重写的Call方法,可以有返回值并且抛出异常");
                        return "callable";
                    }

                    public static void main(String[] args) throws ExecutionException, InterruptedException {
                        MyCallable myCallable=new MyCallable();
                        //利用FutureTask执行Callable并且接受结果
                        FutureTask<String> stringFutureTask = new FutureTask<>(myCallable);
                        //利用线程执行Task任务
                        new Thread(stringFutureTask).start();
                        //接受结果FutureTask.get会发生阻塞情况
                        System.out.println(stringFutureTask.get());

                        System.out.println("MyCallable执行完毕,返回值结果正确接收~");
                    }
                }

 

         调用Callable的第二种实现方案:

                public static void main(String[] args) throws ExecutionException, InterruptedException {
                    MyCallable myCallable=new MyCallable();
                    //创建一个线程池
                    ExecutorService executorService = Executors.newFixedThreadPool(3);
                    //创建线程执行任务,接受任务结果
                    Future<String> future = executorService.submit(myCallable);
                    //接受返回值
                    System.out.println(future.get(2000,TimeUnit.MILLISECONDS));
                    System.out.println("方式二,线程池:MyCallable执行完毕,返回值结果正确接收~");
                    //停止线程池
                    executorService.shutdown();
                }

 

            Future.get()                      方法获取任务执行结果,该方法如果没有返回时,暂时处于阻塞状态
            Future.get(Long timeOut,TimeUnit timeUnit)          可以设置超时时间
            Future.boolean isDone()                  如果线程结束,无论是正常结束还是任务终止都会返回true
            Future.boolean isCanceller()                 如果任务完成前被取消则返回true
            Future.boolean cancel(boolean flag)            方法参数如果传入为true代表中断任务,如果任务中断成功,则返回值为true,如果失败则为false

 

   Future提供三种功能:1.中断任务cancel(true)        2.判断任务是否执行完成isDone()        3.获取任务执行后的结果get()

//中断任务
                boolean cancel = future.cancel(true);
                if(cancel){
                    System.out.println("中断任务成功~");
                }else{
                    //接受返回值
                    System.out.println(future.get(2000,TimeUnit.MILLISECONDS));

                }

 

如果手写Future模式应该怎么样定义?

wait负责阻塞和notify负责唤起阻塞线程

                public class MyFuture {
                    //FLAG相当于数据标识,如果放入数据成功,则返回为true,否则返回为false
                    private static boolean FLAG=false;
                    private String data;

                    public synchronized void setData(String data) throws InterruptedException {
                        Thread.sleep(2000);
                        //赋值操作
                        this.data = data;
                        FLAG=true;
                        //唤起
                        notify();
                    }

                    public synchronized String getData() {
                        //如果获取数据失败
                        if(!FLAG){
                            try {
                                wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        return data;
                    }

                    public static void main(String[] args) {
                        MyFuture future=new MyFuture();
                        new Thread(()->{
                            try {
                                future.setData("张三");
                                System.out.println(future.getData());
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }).start();
                    }
                }

 

posted @ 2020-03-23 12:54  怀鑫  阅读(201)  评论(0编辑  收藏  举报