三.多线程JUC篇-3.18 Future 详细讲解

1.get和interrupt

private static void testGet() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future = executorService.submit(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        });
        //==========================================
        System.out.println("=========I will be printed quickly.==========");
        //==========================================
        
        Thread callerThread = Thread.currentThread();
        new Thread(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //打断了callerThread和future.get()的阻塞
            //要注意,get()阻塞的是调用线程,而不是线程池中的线程
            //对线程池里面的线程没有影响,线程池里面的线程还在执行中
            callerThread.interrupt();
        }).start();
        
        //get()时,会阻塞调用线程
        Integer result = future.get();
        System.out.println(result);
    }

2.GetWithTimeOut

 private static void testGetWithTimeOut() throws InterruptedException, ExecutionException, TimeoutException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future = executorService.submit(() -> {
            try {
                TimeUnit.SECONDS.sleep(10);
                System.out.println("====== The time is longer than timeOut ========");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        });
        
        //该方法对调用者是超时退出的
        //特别要注意,对线程池中的线程没有任何影响,线程还是会一直运行
        //如果需要取消线程池中的线程执行,需要用到cancel,并且此线程是可被中断的
        Integer result = future.get(5, TimeUnit.SECONDS);
        System.out.println(result);
    }
}

3.cancel

简单来说,传入false参数只能取消还没有开始的任务,若任务已经开始了,就任由其运行下去。
当创建了Future实例,任务可能有以下三种状态:

  • 等待状态:此时调用cancel()方法不管传入true还是false都会标记为取消,任务依然保存在任务队列中,但当轮到此任务运行时会直接跳过。
  • 完成状态:此时cancel()不会起任何作用,因为任务已经完成了。
  • 运行中:此时传入true会中断正在执行的任务,传入false则不会中断。

总结:

  • Future.cancel(true)适用于:
    长时间处于运行的任务,并且能够处理interruption

  • Future.cancel(false)适用于:
    (1) 未能处理interruption的任务
    (2) 不清楚任务是否支持取消
    (3) 需要等待已经开始的任务执行完成

3.1 任务完成,取消

private static void testCancel_1() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future = executorService.submit(() -> {
            TimeUnit.SECONDS.sleep(5);
            return 5;
        });
        System.out.println(future.get());
        System.out.println(future.cancel(true));
    }
}
//输出:
5
false    

3.2 任务完成,取消后,再次取消

private static void testCancel_1() throws InterruptedException, ExecutionException {

        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future = executorService.submit(() -> {
            try{
                TimeUnit.SECONDS.sleep(5);
            }catch (InterruptedException e){
                System.out.println( LocalTime.now() +": =========");
            }
            System.out.println( LocalTime.now() +": *********");
            return 5;
        });
        TimeUnit.MILLISECONDS.sleep(10);
        System.out.println( LocalTime.now() +": " + future.cancel(true));
        System.out.println(LocalTime.now() +": " + future.cancel(true));
       // System.out.println(future.get());
    }
  
 //输出:
11:31:13.029: true
11:31:13.029: false
11:31:13.029: =========
11:31:13.030: ********* 

3.3 对没有可中断的任务进行取消

private static void testCancel_3() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newCachedThreadPool();

        Future<Integer> future = executorService.submit(() -> {
            while(true) {
                System.out.println("=====");

            }

        });

        TimeUnit.MILLISECONDS.sleep(10);
        System.out.println(future.cancel(true));
        System.out.println(future.isDone());
        System.out.println(future.isCancelled());
    }
//输出:
//发现会一直打印,任务并没有被取消
//而cancel、isDone、isCancelled都返回了true
//=====
//=====
//true
//true
//true
//=====
....    

3.4 暴力全部停止不可中断的任务

    private static void testCancel_1() throws InterruptedException, ExecutionException {

        ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setDaemon(true);
                return thread;
            }
        });

        Future<Integer> future = executorService.submit(() -> {
            while(true) {
                System.out.println("=====");

            }

        });

        TimeUnit.MILLISECONDS.sleep(10);
        System.out.println(future.cancel(true));
        System.out.println(future.isDone());
        System.out.println(future.isCancelled());
    }

//输出:
//发现任务会取消
//cancel、isDone、isCancelled都返回了true
//=====
//=====
//true
//true
//true
//=====

3.5 interrupted配合cancel

private static void testCancel_1() throws InterruptedException, ExecutionException {

        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future = executorService.submit(() -> {
            while(!Thread.interrupted()) {

            }
            System.out.println( LocalTime.now() +": *********");
            return 5;
        });
        TimeUnit.MILLISECONDS.sleep(10);
        System.out.println( LocalTime.now() +": " + future.cancel(true));
        System.out.println(LocalTime.now() +": " + future.cancel(true));
    }
    
//输出:
13:36:31.089: true
13:36:31.089: *********
13:36:31.089: false

3.6 cancel之后,进行get

private static void testCancel_1() throws InterruptedException, ExecutionException {

        ExecutorService executorService = Executors.newCachedThreadPool();
        Future<Integer> future = executorService.submit(() -> {
            while(!Thread.interrupted()) {

            }
            System.out.println( LocalTime.now() +": *********");
            return 5;
        });
        TimeUnit.MILLISECONDS.sleep(10);
        System.out.println( LocalTime.now() +": " + future.cancel(true));
        System.out.println(future.get());
    }
    
//输出:
13:38:17.640: true
13:38:17.640: *********
Exception in thread "main" java.util.concurrent.CancellationException
	at java.util.concurrent.FutureTask.report(FutureTask.java:121)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.testCancel_1(ExecutorServiceExample1.java:35)
	at com.wangwenjun.concurrent.executors.ExecutorServiceExample1.main(ExecutorServiceExample1.java:16)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值