ExecutorService接口是 java 内置的线程池接口,通过学习接口中的方法,可以快速的掌握 java 内置线程池 的基本使用
原本创建线程池的Demo,需要设置很多参数,现在使用 ExecutorService 类,就可以节省很多设置。
如图:这是直接创建ThreadPoolExecutor 线程池的demo:
需要设置这些参数等:
下面使用 ExecutorService 类 来快速使用线程池,减少原本的一些参数定义。
关闭线程池的方法,前面已经演示过了
启动一次顺序关闭,执行以前提交的任务,但不接受新任务
关闭线程池的方法,前面已经演示过了
停止所有正在执行的任务,暂停处理正在等待的任务,并返回等待执行的任务列表
相当于之前的execute方法。也是往线程提交一个任务。
这里Callable是有返回值的
执行 Runnable 任务,并返回一个表示该任务的 Future。
执行 Runnable 任务,并返回一个表示该任务的 Future。
创建一个默认的线程池对象,里面的线程可重用,且在第一次使用时才创建。
cache:缓存】隐藏
代码演示:
用这个方法创建的线程池,适用于:不需要定制最大线程数和最小线程这些,来个任务就创建个线程,任务做完就取新的任务。
工作线程创建多少不用我们管。
创建一个可重用固定线程数的线程池
Fixed:固定的
如图:最大线程数和最小核心线程数的参数是同一个,是固定的。
创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。
Single:单个的、单一的
创建一个可重用固定线程数的线程池且允许延迟运行或定期执行任务;
这个方法是可以多个线程执行的。
Scheduled:定时、预定、定于
定时的话,得用这个 ScheduledExecutorService 类来创建线程池,才有对应的定时方法。
任务添加到线程池5,定时5秒后再执行
应用场景:比如超时支付
fixed:固定
rate:速度
同一个任务,周期性的执行该任务。
任务提交到线程池后,最开始隔3秒后执行,后面就周期性的每隔5秒执行一次。
任务提交到线程池后,最开始隔3秒后执行,后面就周期性的每隔5秒执行一次
设置情况一:任务执行时间需要2秒
得出结论:只要进入到这个run方法,就会开始计时,不会管任务执行多久
设置情况二:任务执行时间需要10秒,大于周期性时间设置的5秒
得出结论:
只要进入到任务的run方法,就开始计时,不会管任务执行多久,如果任务执行时间已经超过大于周期性时间,那么该任务执行完后,就会立即继续执行。
任务执行时间需要2秒,大于周期性时间设置的5秒
可以看出:这个方法是等任务执行完后,才开始计时的。
适用场景:定时器功能
创建一个单线程执行程序,它允许在给定延迟后运行命令或者定期地执行。
跟上一个方法差不多,区别就是:这个方法是单线程执行的。
上面的在使用这个 java内置线程池时,没有考虑线程计算的结果,但开发中,我们有时需要利用线程进行一些计算,然后获取这些计算的结果,而java中的Future接口就是专门用于描述异步计算结果的,我们可以通过Future 对象获取线程计算的结果;
如有必要,等待计算完成,然后获取其结果。
执行任务的线程因为睡眠5,这期间main线程已经执行了future.get()代码了,那么future.get()在任务还没执行完时能拿到返回值或是null吗?
从源码看,future.get() 如果取不到值会进行阻塞,然后任务线程执行完后,就会唤醒已经阻塞的future.get(),然后future.get()获取到值。
还可以设置超时时间:
如有必要,最多等待为使计算完成所给定的时间之后,获取其结果(如果结果可用)。
任务执行5秒,get的超时时间是6秒,可以正常获取到值
如果任务执行时间是5秒,超时时间设置为4秒。那么就会报超时的错
试图取消对此任务的执行。
如果在 任务执行完成前 将其取消,则返回 true。
执行到 future.isCancelled() 这个代码时,如果任务还没被中断,则返回false
package cn.ljh.algorithmic;
import lombok.SneakyThrows;
import java.util.Date;
import java.util.concurrent.*;
public class ExecutorServiceDemo02
{
@SneakyThrows
public static void main(String[] args)
{
//创建一个线程池
ExecutorService service = Executors.newCachedThreadPool();
//有返回值
Future<String> future = service.submit(new Callable<String>()
{
@Override
public String call() throws Exception
{
System.err.println("线程池线程:当前线程: " + Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(5);
return "66666666 线程池里面的线程执行任务后的结果";
}
});
//中断此任务的执行
//future.cancel(true);
//如果在任务正常完成前将其取消,则返回 true。执行到这里时,任务没有被中断,返回false
System.err.println(future.isCancelled());
System.err.println("main线程:当前线程:"+Thread.currentThread().getName());
System.err.println("isDone()1 : "+future.isDone());
//线程返回的结果,还可以设置超时时间
String result = future.get(4,TimeUnit.SECONDS);
System.err.println("isDone()2 : "+future.isDone());
System.err.println("线程返回的结果:" + result);
}
}