Java并发程序设计(8)线程池之用于定时器

1.1. 线程池用于定时器

线程池用于定时器调度时,只能指定某个时间段后执行任务,而不能指定具体的时间点。

1.2. 只运行一次的定时器

5秒钟后运行指定任务的定时器,定时器任务只会被执行1次。

ScheduledExecutorService  executorService = Executors.newScheduledThreadPool(3);

executorService.schedule( new Runnable(){

@Override

public void run() {

System.out.println("scheduled:" + new Date() + "  " + Thread.currentThread().getId());

}

}, 1000 * 5, TimeUnit.MILLISECONDS );

1.3. 固定比率的定时器

固定比率的定时器会在指定时间段之后首次运行任务,并在之后每隔固定时间段后重复运行任务。以下代码创建一个5秒后首次运行并每隔1秒重复1次的定时器。

ScheduledExecutorService  executorService = Executors.newScheduledThreadPool(3);

executorService.scheduleAtFixedRate( new Runnable(){

@Override

public void run() {

System.out.println("scheduled:" + new Date() + "  " + Thread.currentThread().getId());

}

}, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );

scheduled:Sun Mar 12 19:55:07 CST 2017  8

scheduled:Sun Mar 12 19:55:08 CST 2017  8

scheduled:Sun Mar 12 19:55:09 CST 2017  10

scheduled:Sun Mar 12 19:55:10 CST 2017  10

scheduled:Sun Mar 12 19:55:11 CST 2017  10

scheduled:Sun Mar 12 19:55:12 CST 2017  10

scheduled:Sun Mar 12 19:55:13 CST 2017  11

scheduleAtFixedRate()这个函数的api doc是这样描述的:

Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on. If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the executor. If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.

Parameters:

command the task to execute

initialDelay the time to delay first execution

period the period between successive executions

unit the time unit of the initialDelay and period parameters

Returns:

a ScheduledFuture representing pending completion of the task, and whose get() method will throw an exception upon cancellation

翻译可能不是很准确,大致的意思就是:

创建和执行一个周期性的动作,这个动作在给定的初始时间延迟之后首次使能,并且以给定的时间间隔持续执行。该动作的执行首次发生于initialDelay个时间单位之后,然后是initialDelay+period,initialDelay + 2*period等等。如果定时任务的任何一次执行发生一个异常,后续执行将被停止。如果没有发生任何异常,定时任务将直到线程池执行器终止或取消才终止。如果该定时任务的任何一次执行花费的时间长于它的时间间隔(period),那么后续执行会延迟开始,而不会并行执行。

参数:

command: 待执行的任务。

initialDelay: 初始时间延迟。

period:相邻的执行之间的时间间隔。

unit: 时间单位。

返回值:

一个ScheduledFuture对象,用于表达尚未完成的任务。在任务取消时,其get)方法将抛出一个异常。

任务延迟的情况:

ScheduledExecutorService  executorService = Executors.newScheduledThreadPool(3);

executorService.scheduleAtFixedRate( new Runnable(){

@Override

public void run() {

System.out.println("scheduled:" + new Date() + "  " + Thread.currentThread().getId());

try {

Thread.sleep(1000*3);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );

sleep()导致任务发生延迟,此时任务从每秒执行1次变成了每3秒执行1次。

scheduled:Sun Mar 12 20:55:34 CST 2017  8

scheduled:Sun Mar 12 20:55:37 CST 2017  8

scheduled:Sun Mar 12 20:55:40 CST 2017  10

scheduled:Sun Mar 12 20:55:43 CST 2017  10

scheduled:Sun Mar 12 20:55:46 CST 2017  10

scheduled:Sun Mar 12 20:55:49 CST 2017  10

scheduled:Sun Mar 12 20:55:52 CST 2017  10

scheduled:Sun Mar 12 20:55:55 CST 2017  10

1.4. 固定延时的定时器

ScheduledExecutorService  executorService = Executors.newScheduledThreadPool(3);

executorService.scheduleWithFixedDelay( new Runnable(){

@Override

public void run() {

System.out.println("scheduled:" + new Date() + "  " + Thread.currentThread().getId());

}

}, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );

scheduled:Sun Mar 12 20:51:29 CST 2017  8

scheduled:Sun Mar 12 20:51:30 CST 2017  8

scheduled:Sun Mar 12 20:51:31 CST 2017  10

scheduled:Sun Mar 12 20:51:32 CST 2017  10

scheduled:Sun Mar 12 20:51:33 CST 2017  10

scheduled:Sun Mar 12 20:51:34 CST 2017  10

scheduled:Sun Mar 12 20:51:35 CST 2017  10

scheduled:Sun Mar 12 20:51:36 CST 2017  10

scheduled:Sun Mar 12 20:51:37 CST 2017  11

scheduled:Sun Mar 12 20:51:38 CST 2017  11

任务被延迟的情况:

ScheduledExecutorService  executorService = Executors.newScheduledThreadPool(3);

executorService.scheduleWithFixedDelay( new Runnable(){

@Override

public void run() {

System.out.println("scheduled:" + new Date() + "  " + Thread.currentThread().getId());

try {

Thread.sleep(1000*3);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}, 1000 * 5, 1000*1, TimeUnit.MILLISECONDS );

原来计划每秒执行1次的任务,变成了每4秒执行1次。后续延时周期跟固定比率定时器有差异。固定比率变成了3秒,而固定延时变成了4秒。

固定比率可以理解为前面任务结束后发现执行时间已经超过了延时间隔周期就不在等待而是立即开始执行后续任务。 固定延时可以理解为前面任务完成之后开始正常计算后续任务的延时。

scheduled:Sun Mar 12 20:35:44 CST 2017  8

scheduled:Sun Mar 12 20:35:48 CST 2017  8

scheduled:Sun Mar 12 20:35:52 CST 2017  10

scheduled:Sun Mar 12 20:35:56 CST 2017  10

scheduled:Sun Mar 12 20:36:00 CST 2017  10

scheduled:Sun Mar 12 20:36:04 CST 2017  10

scheduled:Sun Mar 12 20:36:08 CST 2017  10

scheduled:Sun Mar 12 20:36:12 CST 2017  10

scheduled:Sun Mar 12 20:36:16 CST 2017  10

scheduled:Sun Mar 12 20:36:20 CST 2017  10

scheduled:Sun Mar 12 20:36:24 CST 2017  10

scheduled:Sun Mar 12 20:36:28 CST 2017  10

scheduled:Sun Mar 12 20:36:32 CST 2017  10

scheduled:Sun Mar 12 20:36:36 CST 2017  10

时间: 2024-08-08 02:00:25

Java并发程序设计(8)线程池之用于定时器的相关文章

Java并发程序设计(6)线程池之线程数量的控制

1.1. ExecutorService ExecutorService是线程池的接口. Executors是用于创建不同线程池的工具类. 1.2. 线程数量固定的线程池 ExecutorService executorService = Executors.newFixedThreadPool(2); for(int j=0;j<10;j++){ final int t = j; executorService.execute( new Runnable(){ @Override public

Java并发程序设计(7)线程池之异常终止和正常关闭

1.1. 线程池中的线程的异常终止 如果线程池中的线程的任务代码发生异常导致线程终止,线程池会自动创建一个新线程. 对于各种类型的线程池,都是如此.以下代码在单个线程的线程池中抛出一个异常,可以发现后续任务中输出的每个tid的值都不相同. ExecutorService executorService = Executors.newSingleThreadExecutor(); for(int j=0;j<10;j++){ final int t = j; executorService.exe

Java并发程序设计(10)线程池之任务结果的异常处理

1.1. 任务结果的异常处理 如果任务执行过程中发生异常,则get()方法会产生ExecutionException. ExecutorService executorService = Executors.newFixedThreadPool(2); Future<Integer> future = executorService.submit( new Callable(){ @Override public Integer call() throws Exception { throw

Java并发程序设计(9)线程池之获取任务执行结果

1.1. 获取执行结果 使用Callable接口可以方便的获取任务执行结果. ExecutorService executorService = Executors.newFixedThreadPool(2); Future<Integer> future = executorService.submit( new Callable(){ @Override public Integer call() throws Exception { return 1; } }); try { int r

【转】Java并发编程:线程池的使用

Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPool

Java并发基础(六) - 线程池

Java并发基础(六) - 线程池 1. 概述 这里讲一下Java并发编程的线程池的原理及其实现 2. 线程池的基本用法 2.1 线程池的处理流程图 该图来自<Java并发编程的艺术>: 从图中我们可以看出当一个新任务到线程池时,线程池的处理流程如下: 线程池首先判断线程池里面线程数是否达到核心线程数.如果不是则直接创建新线程作为核心线程来执行该任务(该线程作为核心线程不会由于任务的完成而销毁),否则进入下一流程. 判断阻塞队列是否已经满了.如果没满则将该任务放入阻塞队列中,等待核心线程处理,

Java并发编程:线程池的使用(转)

Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPool

Java并发编程:线程池的使用

在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.今天我们就来详细讲解一下Java的线程池,首先我们从最核心的ThreadPoolExecutor类中的方法讲起,

Java并发编程之线程池

一.概述 在执行并发任务时,我们可以把任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程,只要池里有空闲的线程,任务就会分配一个线程执行.在线程池的内部,任务被插入一个阻塞队列(BlockingQueue),线程池里的线程会去取这个队列里的任务. 利用线程池有三个好处: 降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗 提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行 提高线程的可管理性.线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,