【学习】线程池:获取任务执行结果get与取消任务cancel方法

阻塞式和定时式那种获取任务方式更好?

Future获取结果的方式有两种

一个是无参的get方法,
  • 它是阻塞式的,获取结果会一直等到结果输出。
  • 案例如下:
  • 先创建任务类
import java.util.concurrent.Callable;

/**
 * @Description Callable任务
 * @ClassName ResultTask
 * @Date 2022/2/9 20:39
 **/
public class ResultTask implements Callable<Integer> {

    public Integer call() throws Exception {
        return 1+1;
    }
}
  • 然后创建单个线程池获取任务结果
import com.naidou.threadPool.tp04.ResultTask;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @Description 阻塞式get方法
 * @ClassName ThreadPool04
 * @Date 2022/2/11 21:46
 **/
public class ThreadPool05 {

    public static void main(String[] args) {
        // 创建任务
        com.naidou.threadPool.tp04.ResultTask task = new ResultTask();
        // 创建单个线程的线程池
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        // 提交任务
        Future<Integer> future = threadPool.submit(task);
        try {
            // 获取任务执行结果
            Integer result = future.get();
            // 输出任务执行结果
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }

    }

}
  • 输出结果:程序正常输出
    在这里插入图片描述
另一个是有参的get方法
  • 我们可以设置获取结果的超时时间,如果大于超时时间,那么程序会抛出TimeoutException异常
    案例如下:
  • 先创建任务类,设置线程休眠时间为3秒
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * @Description Callable任务
 * @ClassName ResultTask
 * @Date 2022/2/9 20:39
 **/
public class ResultTask01 implements Callable<Integer> {

    public Integer call() throws Exception {
        // 使当前线程休眠3秒钟
        TimeUnit.SECONDS.sleep(3);
        return 1+1;
    }
}
  • 然后创建单个线程获取任务,先设置获取结果超时时间为1秒
import java.util.concurrent.*;

/**
 * @Description 阻塞式get方法
 * @ClassName ThreadPool04
 * @Date 2022/2/11 21:46
 **/
public class ThreadPool051 {

    public static void main(String[] args) {
        // 创建任务
        ResultTask01 task = new ResultTask01();
        // 创建单个线程的线程池
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        // 提交任务
        Future<Integer> future = threadPool.submit(task);
        try {
            // 获取任务执行结果
            Integer result = future.get(1,TimeUnit.SECONDS);
            // 输出任务执行结果
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }

    }

}
  • 输出结果:抛出超时异常,符合预期
    在这里插入图片描述
  • 然后设置超时时间为5秒
// 获取任务执行结果
            Integer result = future.get(5,TimeUnit.SECONDS);
  • 输出结果:3秒后程序正常输出,符合预期
    在这里插入图片描述

总结

  • 两种写法都可以,依据不同业务视情况而定,一般用无参方法比较多。

取消任务的cancel方法的一些困惑

cancel(boolean) 取消任务

true:表示尝试中断正在执行任务的线程(只对执行中的任务有意义)
取消正在执行的任务
  • 创建任务类
import java.util.concurrent.Callable;

/**
 * @Description Callable任务
 * @ClassName ResultTask042
 * @Date 2022/2/9 20:39
 **/
public class ResultTask042 implements Callable<Integer> {

    public Integer call() throws Exception {
        // 计数器
        int i = 0;
        // 当线程没被中断时
        while (!Thread.interrupted()){
            // 递增i
            i++;
        }
        // 输出i
        System.out.println("i的值:"+i);
        // 返回1+1的值
        return 1+1;
    }
}
  • 线程取消正在执行任务
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @Description  取消正在执行的任务
 * @ClassName ThreadPool04
 * @Date 2022/2/11 21:46
 **/
public class ThreadPool042 {

    public static void main(String[] args) {
        // 创建任务
        ResultTask task = new ResultTask();
        // 创建单个线程的线程池
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        // 提交任务
        Future<Integer> future = threadPool.submit(task);
        System.out.println("任务是否完成:" + future.isDone());
        // 取消任务 调用interrupt打断
        boolean cancel = future.cancel(true);
        System.out.println("任务是否取消成功:" + cancel);
        System.out.println("任务是否取消:" + future.isCancelled());
        try {
            // 获取任务执行结果
            Integer result = future.get();
            // 输出任务执行结果
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }
    }
}
  • 输出结果:任务取消成功,并引发CancellationException 异常
    在这里插入图片描述
false:则相反
取消未执行任务
  • 创建任务类
import java.util.concurrent.Callable;

/**
 * @Description Callable任务
 * @ClassName ResultTask
 * @Date 2022/2/9 20:39
 **/
public class ResultTask implements Callable<Integer> {

    public Integer call() throws Exception {
        return 1+1;
    }
}
  • 取消未执行任务
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @Description 取消未执行任务 引发CancellationException 异常
 * @ClassName ThreadPool04
 * @Date 2022/2/11 21:46
 **/
public class ThreadPool04 {

    public static void main(String[] args) {
        // 创建任务
        ResultTask task = new ResultTask();
        // 创建单个线程的线程池
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        // 提交任务
        Future<Integer> future1 = threadPool.submit(task);
        Future<Integer> future2 = threadPool.submit(task);
        // 取消任务 调用interrupt打断 取消未执行任务
        boolean cancel = future2.cancel(false);
        System.out.println("任务是否取消成功:" + cancel);
        System.out.println("任务是否取消:" + future2.isCancelled());
        try {
            // 获取任务执行结果
            Integer result = future2.get();
            // 输出任务执行结果
            System.out.println(result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }

    }
  • 输出结果:任务取消成功,获取结果引发CancellationException 异常
    在这里插入图片描述
取消已完成任务
  • 尝试取消已完成任务
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @Description  尝试取消已完成任务
 * @ClassName ThreadPool04
 * @Date 2022/2/11 21:46
 **/
public class ThreadPool041 {

    public static void main(String[] args) {
        // 创建任务
        ResultTask task = new ResultTask();
        // 创建单个线程的线程池
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        // 提交任务
        Future<Integer> future = threadPool.submit(task);
        try {
            // 获取任务执行结果
            Integer result = future.get();
            // 输出任务执行结果
            System.out.println(result);
            // 取消任务 调用interrupt打断 取消未执行任务
            boolean cancel = future.cancel(false);
            System.out.println("任务是否取消成功:" + cancel);
            System.out.println("任务是否取消:" + future.isCancelled());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            threadPool.shutdown();
        }

    }

}
  • 输出结果:已完成任务无法取消
    在这里插入图片描述

总结

在这里插入图片描述

在这里插入图片描述

参考地址

线程池视频讲解05,06

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值