Interrupt a Quartz job that doing IO

如果你想中断正在执行IO的 Quartz 作业,在你使用 InterruptibleChannel 时这是可行的。引用一下Oracle链接:实现了这个接口的通道,是可中断的:如果一个线程在一个中断通道阻塞I/O操作,另一个线程能调用阻塞的线程的中断方法。这将导致的通道被关闭,被阻塞的线程收到一个ClosedByInterruptException,设置被阻塞的线程的中断状态。因此,获得自己工作的执行线程的作业计划,能保存供以后使用。当Quartz调度中断作业,你可以再调用该线程的interrupt()方法来停止读/写操作。这里有一个简单的例子:

package demo;

// import statements excluded for brevity

public class MyJob implements InterruptableJob {

  private static Logger    LOG              = LoggerFactory.getLogger(MyJob.class);

  private volatile boolean isJobInterrupted = false;

  private JobKey           jobKey           = null;

  private volatile Thread  thisThread;

  public MyJob() {
} public void execute(JobExecutionContext context) throws JobExecutionException {
thisThread = Thread.currentThread();
LOG.info("Thread name of the current job: " + thisThread.getName()); jobKey = context.getJobDetail().getKey();
LOG.info("Job " + jobKey + " executing at " + new Date()); try {
String fileUrl = "http://d2zwv9pap9ylyd.cloudfront.net/terracotta-3.6.1.tar.gz"; // 59 MB
String localFile = "terracotta-3.6.1.tar.gz";
download(fileUrl, localFile);
} catch (ClosedByInterruptException e) {
LOG.info("Caught ClosedByInterruptException... exiting job.");
} catch (IOException e) {
LOG.info("Caught IOException... exiting job.", e);
} finally {
if (isJobInterrupted) {
LOG.info("Job " + jobKey + " did not complete");
} else {
LOG.info("Job " + jobKey + " completed at " + new Date());
}
}
} // this method is called by the scheduler
public void interrupt() throws UnableToInterruptJobException {
LOG.info("Job " + jobKey + " -- INTERRUPTING --");
isJobInterrupted = true;
if (thisThread != null) {
// this called cause the ClosedByInterruptException to happen
thisThread.interrupt();
}
} private void download(String address, String localFileName) throws ClosedByInterruptException, IOException {
URL url = new URL(address);
ReadableByteChannel src = Channels.newChannel(url.openStream());
WritableByteChannel dest = new FileOutputStream(new File(localFileName)).getChannel();
try {
System.out.println("Downloading " + address + " to " + new File(localFileName).getCanonicalPath());
int size = fastChannelCopy(src, dest);
System.out.println("Download completed! " + (size / 1024 / 1024) + " MB");
} finally {
src.close();
dest.close();
}
} // Code copied from http://thomaswabner.wordpress.com/2007/10/09/fast-stream-copy-using-javanio-channels/
private static int fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
int count = 0;
int total = 0;
while ((count = src.read(buffer)) != -1) {
total += count;
// prepare the buffer to be drained
buffer.flip();
// write to the channel, may block
dest.write(buffer);
// If partial transfer, shift remainder down
// If buffer is empty, same as doing clear()
buffer.compact();
}
// EOF will leave buffer in fill state
buffer.flip();
// make sure the buffer is fully drained.
while (buffer.hasRemaining()) {
dest.write(buffer);
}
return total;
}
}

这是我的主类,创建Quartz Scheduler和模拟预期的中断。下载将需要大约40秒完成(59MB文件)。为了看到我们的作业确实是在下载过程中中断,我们启动调度然后休息5秒。注:如果您想看到的作业完成,休息了约40秒。

package demo;

import static org.quartz.DateBuilder.nextGivenSecondDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger; // other imports excluded for brevity public class InterruptExample { public void run() throws Exception {
final Logger log = LoggerFactory.getLogger(InterruptExample.class); log.info("------- Initializing ----------------------"); // First we must get a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler(); log.info("------- Initialization Complete -----------"); log.info("------- Scheduling Jobs -------------------"); // get a "nice round" time a few seconds in the future...
Date startTime = nextGivenSecondDate(null, 1); JobDetail job = newJob(MyJob.class).withIdentity("myJob", "group1").build(); SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
.withSchedule(simpleSchedule()).build(); sched.scheduleJob(job, trigger); // start up the scheduler (jobs do not start to fire until
// the scheduler has been started)
sched.start();
log.info("Scheduler thread's name: " + Thread.currentThread().getName());
log.info("------- Started Scheduler -----------------"); try {
// if you want to see the job to finish successfully, sleep for about 40 seconds
Thread.sleep(5 * 1000L);
// tell the scheduler to interrupt our job
sched.interrupt(job.getKey());
Thread.sleep(3 * 1000L);
} catch (Exception e) {
e.printStackTrace();
} log.info("------- Shutting Down ---------------------"); sched.shutdown(true); log.info("------- Shutdown Complete -----------------");
} public static void main(String[] args) throws Exception {
InterruptExample example = new InterruptExample();
example.run();
}
}

这是日志,说明我们的作业被intterupted提早退出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
INFO [main] ------- Initializing ----------------------
INFO [main] Using default implementation for ThreadExecutor
INFO [main] Job execution threads will use class loader of thread: main
INFO [main] Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
INFO [main] Quartz Scheduler v.2.1.3 created.
INFO [main] RAMJobStore initialized.
INFO [main] Scheduler meta-data: Quartz Scheduler (v2.1.3) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.
 
INFO [main] Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
INFO [main] Quartz scheduler version: 2.1.3
INFO [main] ------- Initialization Complete -----------
INFO [main] ------- Scheduling Jobs -------------------
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
INFO [main] Scheduler thread's name: main
INFO [main] ------- Started Scheduler -----------------
INFO [DefaultQuartzScheduler_Worker-1] Thread name of the current job: DefaultQuartzScheduler_Worker-1
NFO [DefaultQuartzScheduler_Worker-1] Job group1.myJob executing at Mon Apr 16 16:24:40 PDT 2012
 Downloading http://d2zwv9pap9ylyd.cloudfront.net/terracotta-3.6.1.tar.gz to S:\quartz-interrupt-demo\terracotta-3.6.1.tar.gz
INFO [main] Job group1.myJob  -- INTERRUPTING --
INFO [DefaultQuartzScheduler_Worker-1] Caught ClosedByInterruptException... exiting job.
INFO [DefaultQuartzScheduler_Worker-1] Job group1.myJob did not complete
ERROR [DefaultQuartzScheduler_Worker-1] Worker thread was interrupt()'ed.
 java.lang.InterruptedException
 at java.lang.Object.wait(Native Method)
 at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:552)
INFO [main] ------- Shutting Down ---------------------
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.
INFO [main] ------- Shutdown Complete -----------------

原文:http://itindex.net/blog/2012/04/23/1335149680608.html

如何中断正在执行IO的 Quartz 作业的更多相关文章

  1. SQL SERVER 2008复制数据库时发生执行SQL Server代理作业错误

    1. 情况说明 在利用SQL SERVER数据库复制向导,能够很方便的将一个数据库从一台服务器复制到另一台服务器上,具体操作步骤也十分简单. 不过在实际操作过程常发生“执行SQL SERVER代理作业 ...

  2. 4.Netty执行IO事件和非IO任务

    回顾NioEventLoop的run方法流程 IO事件与非IO任务 处理IO事件 处理非IO任务 聚合定时任务到普通任务队列 从普通队列中获取任务 计算任务执行的超时时间 安全执行 计算是否超时 总结 ...

  3. python学习记录_中断正在执行的代码,执行剪切板中的代码,键盘快捷键,魔术命令,输入和输出变量,记录输入和输出变量_

    2018-03-28 00:56:39 中断正在执行的代码 无论是%run执行的脚本还是长时间运行的命令ctrl + cIn [1]: KeyboardInterrupt 执行剪切板中的代码 ctrl ...

  4. quartz2.3.0(七)调度器中断任务执行,手动处理任务中断事件

    job任务类 package org.quartz.examples.example7; import java.util.Date; import org.slf4j.Logger; import ...

  5. 【淘淘】Quartz作业存储与管理

    一.Quartz作业管理和存储方式简介: 作业一旦被调度,调度器需要记住并且跟踪作业和它们的执行次数.如果你的作业是30分钟后或每30秒调用,这不是很有用.事实上,作业执行需要非常准确和即时调用在被调 ...

  6. Spring.Scheduling.Quartz 作业的应用(定时任务和循环触发任务)

    .定时任务的实现,比如有个任务是要晚上2点10分的时候要去触发的,先定义这个任务类RskBookFilterInitDiningService.cs,这里其实有两种实现,一种是需要继承QuartzJo ...

  7. STM32F4XX中断方式通过IO模拟I2C总线Master模式

    STM32的I2C硬核为了规避NXP的知识产权,使得I2C用起来经常出问题,因此ST公司推出了CPAL库,CPAL库在中断方式工作下仅支持无子地址 的器件,无法做到中断方式完成读写大部分I2C器件.同 ...

  8. kettle在linux下面用于shell脚本执行:转换或者作业

    1 将windows下面创建好的转换,放到Linux某一个文件夹下面.如:把0816_em.ktr文件放到/home/cfj/kettle/testdemo下面. 注意里面的数据库用户名和密码可能需要 ...

  9. zigbee通用IO口小作业

    独立新建工程并编写.编译代码,实现按键控制流水灯运行,完成以下任务要求: [1]程序开始运行时,D4.D3.D6.D5灯全亮一会,然后全灭一会,开始进入流水灯. [2]流水灯的运行过程为:D4灯亮,其 ...

随机推荐

  1. HBase(八)HBase的协处理器

    一.协处理器简介 1. 起源 Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执 行求和.计数.排序等操作.比如,在旧版本的(<0.92)Hbase 中,统计数 ...

  2. 使用require.js编写模块化JS

    layout: post title: 使用requirejs编写模块化代码 category: javascript date: 2016-10-22 00:00:00 tags: javascri ...

  3. mysql 新增时,唯一索引冲突时更新

    INSERT INTO table_name(f1 ,f2 ,f3) VALUES(? ,?) on duplicate key update f2 = ? ,f3 = ?

  4. tp5总结(四)

    数据库 1.数据库配置 1-1.配置文件配置[http://ww:7070/tp5-3/public/] 1-2.Db::connect配置[数组和字符串方式][http://ww:7070/tp5- ...

  5. 几种JS&CSS框架

    易用的,图形种类丰富的,美观的几种: 1.bootstrap 文档地址: http://www.cnblogs.com/fnng/p/4446047.html http://www.runoob.co ...

  6. 003 JTA的使用与理解

    一:认识JTA 1.介绍 事物的ACID. 事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity ).一致性 ( Consistency ).隔离性 ( Isolat ...

  7. MySQL集群原理详解

    1. 为什么需要分布式数据库2. MySQL Cluster原理3. MySQL Cluster的优缺点4. MySQL Cluster国内应用5. 参考资料 1. 为什么需要分布式数据库 随着计算机 ...

  8. 启动win8.1时提示 api-ms-win-crt-runtime-l1-1-0.dll丢失

    电脑里没有安装windows的更新KB2999226 到微软官网 https://www.microsoft.com/zh-cn/download/details.aspx?id=49081 下载对应 ...

  9. [leetcode trie]208. Implement Trie (Prefix Tree)

    实现一个字典树 class Trie(object): def __init__(self): self.root = TrieNode() def insert(self, word): cur = ...

  10. Django Q对象

    使用Q 对象进行复杂的查询¶ filter() 等方法中的关键字参数查询都是一起进行“AND” 的. 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象. Q 对象 (django.db ...