ExecutorService是线程池的一个服务,可以随时关闭线程池,是继承Executor的。Executors是个工厂类,专门创建各种线程池。
此类支持以下各种方法:
ExecutorService的方法:
void shutdown()
SecurityException
- 如果安全管理器存在并且关闭,此 ExecutorService 可能操作某些不允许调用者修改的线程(因为它没有保持
RuntimePermission
("modifyThread")),或者安全管理器的checkAccess 方法拒绝访问。
启动一次顺序关闭,执行以前提交的任务,但不接受新任务。如果已经关闭,则调用没有其他作用。
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
timeout
- 最长等待时间
unit
- timeout 参数的时间单位
InterruptedException
- 如果等待时发生中
void execute(Runnable command)
command
- 可运行的任务
RejectedExecutionException
- 如果不能接受执行此任务。
NullPointerException
- 如果命令为 null
在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。
Future<?> submit(Runnable task)
1. newFixedThreadPool
1.1 是一个一开始就创建的时候,你规定好了其中的线程数字,以共享的无界队列方式来运行这些线程。
1.2 当池子冲的所有的线程都在完成任务的时候,新提交的任务就会处于等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续
的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。
1.3 newFixedThreadPool 与cacheThreadPool差不多,也是能reuse就用,但不能随时建新的线程 (因为他开始创建的时候固定好了呢)
1.4 和cacheThreadPool不同,FixedThreadPool,-从方法的源代码看,cache池和fixed 池调用的是同一个底层池,只不过参数不同:
fixed池线程数固定,并且是0秒IDLE(无IDLE)
cache池线程数支持0-Integer.MAX_VALUE
1.5代码:
public static void main(String[] args)throws IOException, InterruptedException {
// 创建一个固定大小的线程池
ExecutorService service = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
System.out.println("创建线程" + i);
Runnable run = new Runnable() {
@Override public void run() {
System.out.println("启动线程");
}
};
// 执行给定的命令 service.execute(run);
}
// 关闭启动线程 service.shutdown();
// 等待子线程结束,再继续执行下面的代码
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
System.out.println("all thread complete"); }
2. newCachedThreadPool
2.1 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。
2.2 随时创建新线程执行任务, 终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用
ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。
-缓存型池子,先查看池中有没有以前建立的线程,如果有,就使用.如果没有,就建一个新的线程加入池中
通常用于执行一些生存期很短的异步型任务
放入CachedThreadPool的线程不必担心其结束,超过TIMEOUT不活动,其会自动被终止。
3. newSingleThreadExecutor (当线程安全要求thread confinement,这东西比较适合)
3.1创建一个使用单个线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线
程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1) 不同,可保证
无需重新 配置此方法所返回的执行程序即可使用其他的线程。
-单例线程,任意时间池中只能有一个线程
-用的是和cache池和fixed池相同的底层池,但线程数目是1-1,0秒IDLE(无IDLE)
4.newScheduledThreadPool (鉴于 Timer 的上述缺陷,Java 5 推出了基于线程池设计的 ScheduledExecutor。其设计思想是,每一个被调度的任务都会由线程池中一个线程 去执行,因此任务是并发执行的,相互之间不会受到干扰。需要注意的是,只有当任务的执行时间到来时,ScheduedExecutor 才会真正启动一个线程,其余时间 ScheduledExecutor 都是在轮询任务的状态。
)
- 调度型线程池
-这个池子里的线程可以按schedule依次delay执行,或周期执行
public class ScheduledExecutorTest implements Runnable { private String jobName = ""; public ScheduledExecutorTest(String jobName) { super(); this.jobName = jobName; } @Override public void run() { System.out.println("execute " + jobName); } public static void main(String[] args) { ScheduledExecutorService service = Executors.newScheduledThreadPool(10); long initialDelay1 = 1; long period1 = 1; // 从现在开始1秒钟之后,每隔1秒钟执行一次job1 service.scheduleAtFixedRate( new ScheduledExecutorTest("job1"), initialDelay1, period1, TimeUnit.SECONDS); long initialDelay2 = 1; long delay2 = 1; // 从现在开始2秒钟之后,每隔2秒钟执行一次job2 service.scheduleWithFixedDelay( new ScheduledExecutorTest("job2"), initialDelay2, delay2, TimeUnit.SECONDS); } } Output: execute job1 execute job1 execute job2 execute job1 execute job1 execute job2 |
展示了 ScheduledExecutorService 中两种最常用的调度方法 ScheduleAtFixedRate 和 ScheduleWithFixedDelay。ScheduleAtFixedRate 每次执行时间为上一次任务开始起向后推一个时间间隔,即每次执行时间为 :initialDelay, initialDelay+period, initialDelay+2*period, …;ScheduleWithFixedDelay 每次执行时间为上一次任务结束起向后推一个时间间隔,即每次执行时间为:initialDelay, initialDelay+executeTime+delay, initialDelay+2*executeTime+2*delay。由此可见,ScheduleAtFixedRate 是基于固定时间间隔进行任务调度,ScheduleWithFixedDelay 取决于每次任务执行的时间长短,是基于不固定时间间隔进行任务调度。