线程池:系列三
阻塞式和定时式那种获取任务方式更好?
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();
}
}
}
- 输出结果:已完成任务无法取消