• Callable的Future模式


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

    无论使用继承Thread类还是实现Runnable接口,还是使用线程池都无法解决这两个问题

        /*
        run方法没有方法 返回值
        run方法不能抛异常,如果想要解决异常,只能 用try-catch
         */
        @Override
        public void run() {
            System.out.println("线程执行的run方法,没有返回值不能,不能抛异常");
        }
    
        public static void main(String[] args) {
            new Thread(new MyThread()).start();
        }

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

      解决方案一: 

    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执行完毕,返回值结果正确接收~");
        }
    }

      控制台结果:

      方解决方案二:

    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();
            //创建一个线程池
            ExecutorService executorService= Executors.newFixedThreadPool(3);
            //创建线程执行额任务,接收任务结果
            Future<String> future=executorService.submit(myCallable);
            //接收返回值
            System.out.println(future.get());
            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.编写测试代码:

    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, TimeoutException {
            //方式二
            MyCallable myCallable=new MyCallable();
            //创建一个线程池
            ExecutorService executorService= Executors.newFixedThreadPool(3);
            //创建线程执行额任务,接收任务结果
            Future<String> future=executorService.submit(myCallable);
            //中断任务
            boolean cancel = future.cancel(true);
    
            if (cancel==true){
                System.out.println("中断任务成功");
            }else{
               System.out.println(future.get(2000,TimeUnit.MILLISECONDS));
            }
    
            //接收返回值
            System.out.println(future.get());
            System.out.println("方式二:线程池:MyCallable执行完毕,返回值结果正确接收");
    
            //停止线程池
            executorService.shutdown();
        }
    }

      

      控制台结果:


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

    //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();
        }
  • 相关阅读:
    Sql server2008如何导入Excel文件数据?
    oracle和sql server中,取前10条数据语法的区别
    如何将两个字段合成一个字段显示(oracle和sqlserver的区别)
    php递归注意事项
    PHP实现执行定时任务
    商城怎么使用ajax?
    添加新权限管理
    PHP判断一个JSON对象是否含有某一个属性的方法
    centos 中查找文件、目录、内容
    phpStorm中如何不让其自动添加封闭大括号?
  • 原文地址:https://www.cnblogs.com/szhhhh/p/12553278.html
Copyright © 2020-2023  润新知