while (queue.isempty() && newtasksmaybescheduled) queue.wait(); if (queue.isempty()) break; // Queue is empty and will forever remain; die if (!taskfi

Similar documents

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

EJB-Programming-4-cn.doc

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

chp6.ppt

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

JavaIO.PDF

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

Microsoft Word - 01.DOC

《大话设计模式》第一章

untitled

Java

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

雲端 Cloud Computing 技術指南 運算 應用 平台與架構 10/04/15 11:55:46 INFO 10/04/15 11:55:53 INFO 10/04/15 11:55:56 INFO 10/04/15 11:56:05 INFO 10/04/15 11:56:07 INFO

Chapter 9: Objects and Classes

BPS6.0 Web服务集成和短流程功能使用手册

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

電機工程系認可證照清單 /7/1

FP.pdf


9, : Java 19., [4 ]. 3 Apla2Java Apla PAR,Apla2Java Apla Java.,Apla,,, 1. 1 Apla Apla A[J ] Get elem (set A) A J A B Intersection(set A,set B) A B A B

Learning Java

javaexample-02.pdf

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

"+handlermethod.getbean().getclass().getname()); public void aftercompletion(httpservletrequest req, HttpServletResponse resp, Object handler, Excepti

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

内 容 提 要 将 JAVA 开 发 环 境 迁 移 到 Linux 系 统 上 是 现 在 很 多 公 司 的 现 实 想 法, 而 在 Linux 上 配 置 JAVA 开 发 环 境 是 步 入 Linux 下 JAVA 程 序 开 发 的 第 一 步, 本 文 图 文 并 茂 地 全 程 指

开放数据处理服务 ODPS 批量数据通道

附录J:Eclipse教程

ebook39-6

FileMaker 16 ODBC 和 JDBC 指南

java2d-4.PDF

FileMaker 15 ODBC 和 JDBC 指南

1.JasperReport ireport JasperReport ireport JDK JDK JDK JDK ant ant...6

使用MapReduce读取XML文件

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

2009年9月全国计算机等级考试二级Java真题及答案

untitled

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

Microsoft PowerPoint - Java - Lecture 4 Thread & JDBC.ppt

Swing-02.pdf

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

Microsoft PowerPoint - plan08.ppt

无类继承.key

构建 Bluetooth 移动应用 主讲人 : 任凯 微信 :kaiser-tech 2016 年 5 月 6 日 3

JBuilder Weblogic

Java 1 Java String Date

Microsoft PowerPoint - 09Future

输入 project name 选择完成

Microsoft PowerPoint - 14Threads.ppt

新版 明解C++入門編

IoC容器和Dependency Injection模式.doc

北 风 网 讲 师 原 创 作 品 ---- 仅 供 学 员 内 部 交 流 使 用 前 言 吾 尝 终 日 而 思 矣, 不 如 须 臾 之 所 学 也 ; 吾 尝 跂 而 望 矣, 不 如 登 高 之 博 见 也 登 高 而 招, 臂 非 加 长 也, 而 见

<4D F736F F D20C8EDC9E82DCFC2CEE7CCE22D3039C9CF>

建模与图形思考

untitled

chp11.ppt

<4D F736F F F696E74202D20B5DA35D5C220D2ECB3A3BACDB6E0CFDFB3CC2E BBCE6C8DDC4A3CABD5D>

任務二 : 產生 20 個有炸彈的磚塊, 放在隨機的位置編輯 Block 類別的程式碼 import greenfoot.; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) Write a description of class

Microsoft PowerPoint - ch02

Hive:用Java代码通过JDBC连接Hiveserver

<4D F736F F F696E74202D20B5DA3035D5C220C3E6CFF2B6D4CFF3B8DFBCB6B3CCD0F2C9E8BCC6>

并发程序设计

Guava学习之Resources

全国计算机技术与软件专业技术资格(水平)考试

( 总 第 1073 期 ) 浙 江 省 人 民 政 府 主 办 2015 年 3 月 17 日 出 版 省 政 府 令 省 政 府 文 件 目 录 浙 江 省 大 型 群 众 性 活 动 安 全 管 理 办 法 ( 浙 江 省 人 民 政 府 令 第 333 号 ) (3) 浙 江 省 人 民 政

Microsoft Word - 投影片ch15

基于CDIO一体化理念的课程教学大纲设计

1.5招募说明书(草案)

软件工程文档编制

Transcription:

深入浅出 Java Concurrency (32): 线程池 part 5 周期性任务调度 周期性任务调度前世 在 JDK 5.0 之前,java.util.Timer/TimerTask 是唯一的内置任务调度方法, 而且在很长一段 时间里很热衷于使用这种方式进行周期性任务调度 首先研究下 Timer/TimerTask 的特性 ( 至于 javax.swing.timer 就不再研究了 ) public void schedule(timertask task, long delay, long period) { if (delay < 0) throw new IllegalArgumentException("Negative delay."); if (period <= 0) throw new IllegalArgumentException("Non-positive period."); sched(task, System.currentTimeMillis()+delay, -period); public void scheduleatfixedrate(timertask task, long delay, long period) { if (delay < 0) throw new IllegalArgumentException("Negative delay."); if (period <= 0) throw new IllegalArgumentException("Non-positive period."); sched(task, System.currentTimeMillis()+delay, period); public class Timer { private TaskQueue queue = new TaskQueue(); /** * The timer thread. */ private TimerThread thread = new TimerThread(queue); java.util.timerthread.mainloop() private void mainloop() { while (true) { TimerTask task; boolean taskfired; synchronized(queue) { // Wait for queue to become non-empty

while (queue.isempty() && newtasksmaybescheduled) queue.wait(); if (queue.isempty()) break; // Queue is empty and will forever remain; die if (!taskfired) // Task hasn't yet fired; wait queue.wait(executiontime - currenttime); if (taskfired) // Task fired; run it, holding no locks task.run(); catch(interruptedexception e) { 上面三段代码反映了 Timer/TimerTask 的以下特性 : Timer 对任务的调度是基于绝对时间的 所有的 TimerTask 只有一个线程 TimerThread 来执行, 因此同一时刻只有一个 TimerTask 在执行 任何一个 TimerTask 的执行异常都会导致 Timer 终止所有任务 由于基于绝对时间并且是单线程执行, 因此在多个任务调度时, 长时间执行的任务被执行后有可能导致短时间任务快速在短时间内被执行多次或者干脆丢弃多个任务 由于 Timer/TimerTask 有这些特点 ( 缺陷 ), 因此这就导致了需要一个更加完善的任务调 度框架来解决这些问题 周期性任务调度今生 java.util.concurrent.scheduledexecutorservice 的出现正好弥补了 Timer/TimerTask 的缺 陷 public interface ScheduledExecutorService extends ExecutorService { public ScheduledFuture<?> schedule(runnable command, long delay, TimeUnit unit); public <V> ScheduledFuture<V> schedule(callable<v> callable, long delay, TimeUnit unit); public ScheduledFuture<?> scheduleatfixedrate(runnable command, long initialdelay, long period, TimeUnit unit); public ScheduledFuture<?> schedulewithfixeddelay(runnable command,

long initialdelay, long delay, TimeUnit unit); 首先 ScheduledExecutorService 基于 ExecutorService, 是一个完整的线程池调度 另外在 提供线程池的基础上增加了四个调度任务的 API schedule(runnable command,long delay, TimeUnit unit): 在指定的延迟时间一次 性启动任务 (Runnable), 没有返回值 schedule(callable<v> callable, long delay, TimeUnit unit): 在指定的延迟时间一次 性启动任务 (Callable), 携带一个结果 scheduleatfixedrate(runnable command,long initialdelay,long period,timeunit unit): 建并执行一个在给定初始延迟后首次启用的定期操作, 后续操作具有给定的 周期 ; 也就是将在 initialdelay 后开始执行, 然后在 initialdelay+period 后 执行, 接着在 initialdelay + 2 * period 后执行, 依此类推 如果任务的任 何一个执行遇到异常, 则后续执行都会被取消 否则, 只能通过执行程序的取消或 终止方法来终止该任务 如果此任务的任何一个执行要花费比其周期更长的时间, 则将推迟后续执行, 但不会同时执行 schedulewithfixeddelay(runnable command,long initialdelay,long delay,timeunit unit): 创建并执行一个在给定初始延迟后首次启用的定期操作, 随 后, 在每一次执行终止和下一次执行开始之间都存在给定的延迟 如果任务的任一 执行遇到异常, 就会取消后续执行 否则, 只能通过执行程序的取消或终止方法来 终止该任务 上述 API 解决了以下几个问题 : ScheduledExecutorService 任务调度是基于相对时间, 不管是一次性任务还是周期性任务都是相对于任务加入线程池 ( 任务队列 ) 的时间偏移 基于线程池的 ScheduledExecutorService 允许多个线程同时执行任务, 这在添加多种不同调度类型的任务是非常有用的 同样基于线程池的 ScheduledExecutorService 在其中一个任务发生异常时会退出执行线程, 但同时会有新的线程补充进来进行执行 ScheduledExecutorService 可以做到不丢失任务 下面的例子演示了一个任务周期性调度的例子 package xylz.study.concurrency.executor; import java.util.concurrent.executors; import java.util.concurrent.scheduledexecutorservice; import java.util.concurrent.timeunit; public class ScheduledExecutorServiceDemo { public static void main(string[] args) throws Exception{ ScheduledExecutorService execservice = Executors.newScheduledThreadPool(3); execservice.scheduleatfixedrate(new Runnable() {

llis()); llis()); public void run() { System.out.println(Thread.currentThread().getName()+" -> "+System.currentTimeMi Thread.sleep(2000L); catch (Exception e) { e.printstacktrace();, 1, 1, TimeUnit.SECONDS); // execservice.schedulewithfixeddelay(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()+" -> "+System.currentTimeMi Thread.sleep(2000L); catch (Exception e) { e.printstacktrace();, 1, 1, TimeUnit.SECONDS); Thread.sleep(5000L); execservice.shutdown(); 一次可能的输出如下 : pool-1-thread-1 -> 1294672392657 pool-1-thread-2 -> 1294672392659 pool-1-thread-1 -> 1294672394657 pool-1-thread-2 -> 1294672395659 pool-1-thread-1 -> 1294672396657 在这个例子中启动了默认三个线程的线程池, 调度两个周期性任务 第一个任务是每隔 1 秒执行一次, 第二个任务是以固定 1 秒的间隔执行, 这两个任务每次执行的时间都是 2 秒 上面的输出有以下几点结论 : 任务是在多线程中执行的, 同一个任务应该是在同一个线程中执行 scheduleatfixedrate 是每次相隔相同的时间执行任务, 如果任务的执行时间比周期还长, 那么下一个任务将立即执行 例如这里每次执行时间 2 秒, 而周期时间只有 1 秒, 那么每次任务开始执行的间隔时间就是 2 秒 schedulewithfixeddelay 描述是下一个任务的开始时间与上一个任务的结束时间间隔相同 流入这里每次执行时间 2 秒, 而周期时间是 1 秒, 那么两个任务开始执行的间隔时间就是 2+1=3 秒

事实上 ScheduledExecutorService 的实现类 ScheduledThreadPoolExecutor 是继承线程池类 ThreadPoolExecutor 的, 因此它拥有线程池的全部特性 但是同时又是一种特殊的线程池, 这个线程池的线程数大小不限, 任务队列是基于 DelayQueue 的无限任务队列 具体的结构和算法在以后的章节中分析 由于 ScheduledExecutorService 拥有 Timer/TimerTask 的全部特性, 并且使用更简单, 支持并发, 而且更安全, 因此没有理由继续使用 Timer/TimerTask, 完全可以全部替换 需要说明的一点事构造 ScheduledExecutorService 线程池的核心线程池大小要根据任务数来定, 否则可能导致资源的浪费 上一篇 : 线程池 part 4 线程池任务拒绝策略目录下一篇 : 线程池 part 6 线程池的 实现及原理 (1)