1.quartz高度抽象为任务、触发器、调度器
任务:job提供需要执行的任务,程序员实现该接口,在执行job时每次都要创建一个job实例,所以jobdetail接收job的实现类创建实例。同时对job的描述也在jobdetail的构造函数中标明,如调度时的组名和job名称。
触发器:规定时间触发规则,有2个类SimpleTrigger(触发一次或固定间隔周期)CronTrigger(实现cron表达式实现复杂方案),其中Trigger可以和quartz定义的Calendar结合针对一些时间进行包含或者排除(与java原生态Calendar不一样),在org.quartz.implCalendar包下有多种实现类。
调度器(scheduler):它是quartz的独立运行容器,Trigger和Jobdetail可以注册到该容器中(有各自的组和名称),trigger的组和名称合起来必须唯一,同理jobdetail也是组和名称合起来必须为,因为类型不相同所以在2个不同集合中。将Trigger和jobdetail进行绑定实现功能执行,一个job对应多个trigger但是一个trigger只能对应一个job。SchedulerFactory创建scheduler实例,在scheduler中有一个schedulerContext,保存着上下文和servletContext类似。
线程池(ThreadPool):scheduler通过线程池对任务进行调用。
状态job:在job中有一个标签子接口(statefulJob)标注接口是有无状态,有状态job表示当次的执行将影响后面的job执行,无状态job则不会。再job中有一个JobDataMap保存着数据,无状态的每次会复制一个该对象,而有状态的会共享该对象。因此无状态可以并发执行,有状态的就需要等待。一般使用无状态job。如果quartz启动数据库持久化任务调度,则无状态的在注册时保存一次,有状态的每次执行都需要保存。
trigger也有自己的jobdatamap属性,但是每次启动时不会持久化到数据库中。
quartz事件机制:job执行前后,trigger触发前后,scheduler调度前后都可以注册事件进行监听。
2.与spring集成
JobDetailFactoryBean属性:
jobclass实现job的类
beanName默认是bean的id
jobDataAsMap给jobdatamap中输入值
applicationContextJobDataKey指定一个名词在job实现类中可以引用spring的应用上下文
jobListenerNames:指定监听的类名
MethodInvokingJobDetailFactoryBean(这种方式不能持久化)
可以实现把一个业务bean的某个方式封装成具有job实现类的形式提供给任务调度器(前提是这个方法不能有参数)
创建触发器bean简单
创建调度器和spring容器的生命周期进行了关联,并且代替了quartz自身的配置文件,可以自定义property配置文件,还有一些配置如:
calendars为调度器添加calendar
jobdetails向调度器添加jobdetail
autoStartup是否自动启动,不启动则需要程序中启动
starupDelay 延迟多少秒启动scheduler
package com.kay.quartz;
public class QuartzJob {
public void work() {
System.out.println("Quartz的任务调度!!!");
}
}
<beans>
<!-- 要调用的工作类 -->
<bean id="quartzJob" class="com.kay.quartz.QuartzJob"></bean>
<!-- 定义调用对象和调用对象的方法 -->
<bean id="jobtask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- 调用的类 -->
<property name="targetObject">
<ref bean="quartzJob"/>
</property>
<!-- 调用类中的方法 -->
<property name="targetMethod">
<value>work</value>
</property>
</bean>
<!-- 定义触发时间 -->
<bean id="doTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="jobtask"/>
</property>
<!-- cron表达式 -->
<property name="cronExpression">
<value>10,15,20,25,30,35,40,45,50,55 * * * * ?</value>
</property>
</bean>
<!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序 -->
<bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="doTime"/>
</list>
</property>
</bean>
</beans>
测试程序:
public static void main(String[] args) {
System.out.println("Test start.");
ApplicationContext context = new ClassPathXmlApplicationContext("quartz-config.xml");
//如果配置文件中将startQuertz bean的lazy-init设置为false 则不用实例化
//context.getBean("startQuertz");
System.out.print("Test end..");
}
3.jdk提供的timer和timertask类:timertask相当于任务,timer相当于调度器
timertask是一个虚类,需要继承重写(有3个重载方法)
timer只能在固定周期时间调用任务方法。所有的timertask都在该timer下执行所有有时候会出现延迟,因此需要每次执行的任务短。
如果要销毁timer需要使用cancel方法。
java线程分为用户线程和守护线程,垃圾回收器就是守护线程,主要是服务用户线程,当用户线程全部执行完成守护线程也会自动终止,设置线程我守护线程方法为:Thread.setDaemon(true);
4.Executor主要实现任务提交和任务执行解耦
http://blog.****.net/mack415858775/article/details/51508831
java通过Executors提供四种线程池,分别为:
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
(1) newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。示例代码如下:
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(index);
}
});
}
}
}
线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
(2) newFixedThreadPool(项目用过)
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。示例代码如下:
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
} 因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()
(3) newScheduledThreadPool
创建一个定长线程池,支持定时及周期性任务执行。延迟执行示例代码如下:
package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
}
}
表示延迟3秒执行。
定期执行示例代码如下:
package test;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
}
}
表示延迟1秒后每3秒执行一次
(4) newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。示例代码如下:
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExecutorTest {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
结果依次输出,相当于顺序执行各个任务。
单独使用timer、quartz、executor创建的线程默认是非守护线程,在程序结束后任然会继续执行,如果使用spring注入将这些调度开启和关闭与spring容器进行关联,spring容器启动调度任务开始,应用程序结束(spring容器关闭)调度任务停止。
创建的静态成员是classloader级别,如果web程序停止这些变量会从JVM中删除,而线程是JVM级别,如果在应用程序中启动线程在应用程序关闭后并不会回收该线程。
相关文章
- CFS 调度器两种调度类型普通调度 和 组调度
- 恢复被病毒禁用的任务管理器和注册表编辑器
- TSL 和 SSL 是什么?它们有何关系?-定义:SSL(安全套接层)是一种早期的加密协议,用于在互联网通信中保障数据传输的安全性。它通过加密和身份验证机制,确保客户端(如浏览器)与服务器之间的通信不被窃听或篡改。 版本:SSL 1.0(未发布)、SSL 2.0(1995年,已废弃)、SSL 3.0(1996年,已淘汰)。 问题:SSL 3.0 及早期版本存在严重安全漏洞(如 POODLE 攻击),目前已被现代系统禁用。 2. TLS(Transport Layer Security) 定义:TLS(传输层安全协议)是 SSL 的继任者,旨在提供更安全的通信协议。TLS 由国际互联网工程任务组(IETF)标准化,逐步替代了 SSL。 版本:TLS 1.0(1999年,已淘汰)、TLS 1.1(2006年,已淘汰)、TLS 1.2(2008年,广泛使用)、TLS 1.3(2018年,最新标准)。 优势:更强的加密算法(如 AES、ChaCha20)、更高效的握手过程、支持前向保密(Perfect Forward Secrecy)等。 SSL 与 TLS 的关系 继承关系 TLS 直接基于 SSL 3.0 设计,可以视为 SSL 的升级版。TLS 1.0 最初命名为 SSL 3.1,后因标准化需要更名为 TLS。 协议兼容性
- Celery(二)Celery执行异步、延迟和定时任务
- java的nio之:java的bio流下实现的socket服务器同步阻塞模型和socket的伪异步的socket服务器的通信模型
- Skynet服务器框架(八) 任务和消息调度机制
- 语义通信论文略读(十四)线性编码和传输的优化+边缘服务器执行CV任务-CV-Cast:面向计算机视觉的线性编码和传输
- 【05Eclipse 视图】Eclipse 视图详解:导航、包资源管理器、任务、属性和调试视图功能详细介绍
- 【Windows】任务管理器无法解决的问题?试试`tasklist`和`taskkill`命令
- MySQL计划任务(事件调度器)