java定时任务线程池源码_java线程定时器

hacker|
106

文章目录:

java代码启动一个定时任务

在应用里经常都有用到在后台跑定时任务的需求。举个例子,比如需要在服务后台跑一个定时任务来进行非实时计算,清除临时数据、文件等。在本文里,3种不同的实现方法:

普通thread实现

TimerTask实现

ScheduledExecutorService实现

1.普通thread

这是最常见的,创建一个thread,然后让它在while循环里一直运行着,通过sleep方法来达到定时任务的效果。这样可以快速简单的实现,代码如下:

public class Task1 {

public static void main(String[] args) {

// run in a second

final long timeInterval = 1000;

Runnable runnable = new Runnable() {

public void run() {

while (true) {

// ------- code for task to run

System.out.println("Hello !!");

// ------- ends here

try {

Thread.sleep(timeInterval);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

};

Thread thread = new Thread(runnable);

thread.start();

}

}

2.用Timer和TimerTask

上面的实现是非常快速简便的,但它也缺少一些功能。

用Timer和TimerTask的话与上述方法相比有如下好处:

当启动和去取消任务时可以控制

第一次执行任务时可以指定你想要的delay时间

在实现时,Timer类可以调度任务,TimerTask则是通过在run()方法里实现具体任务。

Timer实例可以调度多任务。

当Timer的构造器被调用时,创建了一个线程,这个线程可以用来调度任务:

import java.util.Timer;

import java.util.TimerTask;

public class Task2 {

public static void main(String[] args) {

TimerTask task = new TimerTask() {

@Override

public void run() {

// task to run goes here

System.out.println("Hello !!!");

}

};

Timer timer = new Timer();

long delay = 0;

long intevalPeriod = 1 * 1000;

// schedules the task to be run in an interval

timer.scheduleAtFixedRate(task, delay,

intevalPeriod);

} // end of main

}

3.ScheduledExecutorService

ScheduledExecutorService是从Java SE 5的java.util.concurrent里,做为并发工具类被引进的,这是最理想的定时任务实现方式。

相比于上两个方法,它有以下好处:

相比于Timer的单线程,它是通过线程池的方式来执行任务的

可以很灵活的去设定第一次执行任务delay时间

提供了良好的约定,以便设定执行的时间间隔

通过ScheduledExecutorService#scheduleAtFixedRate展示这个例子,通过代码里参数的控制,首次执行加了delay时间:

import java.util.concurrent.Executors;

import java.util.concurrent.ScheduledExecutorService;

import java.util.concurrent.TimeUnit;

public class Task3 {

public static void main(String[] args) {

Runnable runnable = new Runnable() {

public void run() {

// task to run goes here

System.out.println("Hello !!");

}

};

ScheduledExecutorService service = Executors

.newSingleThreadScheduledExecutor();

service.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS);

}

}

典型Java线程池的代码及其各部分功能介绍

( )根据xml文件来管理线程池的最大最小线程数( )对线程池通过Timer定期扫描以防止线程未激活 ( )通过某一个变量(本程序中是freeThreadCount)来得到空闲线程的数目 一 配置xml(listen xml)是 ?xml version= encoding= UTF ?configConsumeThreadPoolminPools /minPools ! 线程池最小线程 maxPools /maxPools! 线程池最大线程 checkThreadPeriod /checkThreadPeriod ! 检查线程池中线程的周期 分钟 /ConsumeThreadPool/config 二 对于ConsumeThreadPoolPara的javabean: import java io *;public class ConsumeThreadPoolPara implements Serializable{private int minPools;private int maxPools;private int checkThreadPeriod;public int getMinPools(){return minPools;}public int getMaxPools(){return maxPools;}public int getCheckThreadPeriod(){return checkThreadPeriod;}public void setMinPools(int minPools){this minPools = minPools;}public void setMaxPools(int maxPools){this maxPools = maxPools;}public void setCheckThreadPeriod(int checkThreadPeriod){this checkThreadPeriod = checkThreadPeriod;}public String toString(){return minPools+ + maxPools+ +checkThreadPeriod;}public ConsumeThreadPoolPara() {}public static void main(String[] args) {ConsumeThreadPoolPara consumeThreadPool = new ConsumeThreadPoolPara();}} 三 解析xml程序代码(生成ConsumeThreadPoolPara) 使用jdom解析 import jdom *;import jdom input SAXBuilder;import java io *;import java util *;public class ParseConfig {static Hashtable Listens = null;static ConnPara connpara = null;static ConsumeThreadPoolPara consumeThreadPoolPara = null;private static String configxml = listen xml ;static{getConsumeThreadPoolPara(); //得到消费的线程池的参数}/*** 装载文档* @return 返回根结点* @throws JDOMException*/public static Element loadDocument() throws JDOMException{SAXBuilder parser = new SAXBuilder(); // 新建立构造器try {Document document = parser build(configxml);Element root = document getRootElement();return root;}catch(JDOMException e){logger error( listen xml文件格式非法! );throw new JDOMException();}}public static ConsumeThreadPoolPara getConsumeThreadPoolPara(){if(consumeThreadPoolPara ==null){try {Element root = loadDocument();Element consumeThreadPool = root getChild( ConsumeThreadPool );if (consumeThreadPool != null) { //代表有数据库配置consumeThreadPoolPara = new ConsumeThreadPoolPara();Element minPools = consumeThreadPool getChild( minPools );consumeThreadPoolPara setMinPools(Integer parseInt(minPools getTextTrim()));Element maxPools = consumeThreadPool getChild( maxPools );consumeThreadPoolPara setMaxPools(Integer parseInt(maxPools getTextTrim()));Element checkThreadPeriod = consumeThreadPool getChild( checkThreadPeriod );consumeThreadPoolPara setCheckThreadPeriod(Integer parseInt(checkThreadPeriod getTextTrim()));}}catch (JDOMException e) {}}return consumeThreadPoolPara;}} 四 线程池源代码 import java util *;/*** pTitle: 线程池/p* pDescription: 采集消费模块/p* pCopyright: Copyright (c) /p* pCompany: /p* @author 张荣斌* @version */public class ThreadPool {private static int minPools = ; //最小连接池数目private static int maxPools = ; //最大连接池数目private static int checkThreadPeriod = ; //检查连接池的周期ArrayList m_ThreadList; //工作线程列表LinkedList m_RunList = null; //工作任务列表int totalThread = ; //总线程数static int freeThreadCount = ; //未被使用的线程数目private java util Timer timer = null; //定时器static Object o = new Object();static{ //先初始化线程池的参数ConsumeThreadPoolPara consumeThreadPoolPara = ParseConfig getConsumeThreadPoolPara();if(consumeThreadPoolPara!=null){minPools = consumeThreadPoolPara getMinPools();maxPools = consumeThreadPoolPara getMaxPools();checkThreadPeriod = consumeThreadPoolPara getCheckThreadPeriod()* * ;}}public void setMinPools(int minPools){this minPools = minPools;}public void setMaxPools(int maxPools){this maxPools = maxPools;}public void setCheckThreadPeriod(int checkThreadPeriod){this checkThreadPeriod = checkThreadPeriod;}public ThreadPool() {m_ThreadList=new ArrayList();m_RunList=new LinkedList();for(int i= ;iminPools;i++){WorkerThread temp=new WorkerThread();totalThread = totalThread + ;m_ThreadList add(temp);temp start();try{Thread sleep( );}catch(Exception e){}}timer = new Timer(true); //启动定时器timer schedule(new CheckThreadTask(this) checkThreadPeriod);}/*** 当有一个工作来的时候启动线程池的线程* 当空闲线程数为 的时候 看总线程是否小于最大线程池的数目 就new一个新的线程 否则sleep 直到有空闲线程为止;* 当空闲线程不为 则将任务丢给空闲线程去完成* @param work*/public synchronized void run(String work){if (freeThreadCount == ) {if(totalThreadmaxPools){WorkerThread temp = new WorkerThread();totalThread = totalThread + ;m_ThreadList add(temp);temp start();synchronized(m_RunList){m_RunList add(work);m_RunList notify();}}else{while (freeThreadCount == ) {try {Thread sleep( );}catch (InterruptedException e) {}}synchronized(m_RunList){m_RunList add(work);m_RunList notify();}}} else {synchronized(m_RunList){m_RunList add(work);m_RunList notify();}}}/*** 检查所有的线程的有效性*/public synchronized void checkAllThreads() {Iterator lThreadIterator = erator();while (lThreadIterator hasNext()) { //逐个遍厉WorkerThread lTestThread = (WorkerThread) lThreadIterator next();if (! (lTestThread isAlive())) { //如果处在非活动状态时lTestThread = new WorkerThread(); //重新生成个线程lTestThread start(); //启动}}}/*** 打印调试信息*/public void printDebugInfo(){System out println( totalThread= +totalThread);System out println( m_ThreadList size()= +m_ThreadList size());}/**** pTitle: 工作线程类/p* @author 张荣斌* @version */class WorkerThread extends Thread{boolean running = true;String work;public void run(){while(running){synchronized(o){freeThreadCount++;}synchronized(m_RunList){while(m_RunList size() == ){try{m_RunList wait();if(!running) return;}catch(InterruptedException e){} lishixinzhi/Article/program/Java/gj/201311/27379

java线程池怎么实现

要想理解清楚java线程池实现原理,明白下面几个问题就可以了:

(1):线程池存在哪些状态,这些状态之间是如何进行切换的呢?

(2):线程池的种类有哪些?

(3):创建线程池需要哪些参数,这些参数的具体含义是什么?

(4):将任务添加到线程池之后运行流程?

(5):线程池是怎么做到重用线程的呢?

(6):线程池的关闭

首先回答第一个问题:线程池存在哪些状态;

查看ThreadPoolExecutor源码便知晓:

[java] view plain copy

// runState is stored in the high-order bits

private static final int RUNNING    = -1  COUNT_BITS;

private static final int SHUTDOWN   =  0  COUNT_BITS;

private static final int STOP       =  1  COUNT_BITS;

private static final int TIDYING    =  2  COUNT_BITS;

private static final int TERMINATED =  3  COUNT_BITS;

存在5种状态:

1Running:可以接受新任务,同时也可以处理阻塞队列里面的任务;

2Shutdown:不可以接受新任务,但是可以处理阻塞队列里面的任务;

3Stop:不可以接受新任务,也不处理阻塞队列里面的任务,同时还中断正在处理的任务;

4Tidying:属于过渡阶段,在这个阶段表示所有的任务已经执行结束了,当前线程池中是不存在有效的线程的,并且将要调用terminated方法;

5Terminated:终止状态,这个状态是在调用完terminated方法之后所处的状态;

那么这5种状态之间是如何进行转换的呢?查看ThreadPoolExecutor源码里面的注释便可以知道啦:

[java] view plain copy

* RUNNING - SHUTDOWN

*    On invocation of shutdown(), perhaps implicitly in finalize()

* (RUNNING or SHUTDOWN) - STOP

*    On invocation of shutdownNow()

* SHUTDOWN - TIDYING

*    When both queue and pool are empty

* STOP - TIDYING

*    When pool is empty

* TIDYING - TERMINATED

*    When the terminated() hook method has completed

从上面可以看到,在调用shutdown方法的时候,线程池状态会从Running转换成Shutdown;在调用shutdownNow方法的时候,线程池状态会从Running/Shutdown转换成Stop;在阻塞队列为空同时线程池为空的情况下,线程池状态会从Shutdown转换成Tidying;在线程池为空的情况下,线程池状态会从Stop转换成Tidying;当调用terminated方法之后,线程池状态会从Tidying转换成Terminate;

在明白了线程池的各个状态以及状态之间是怎么进行切换之后,我们来看看第二个问题,线程池的种类:

(1):CachedThreadPool:缓存线程池,该类线程池中线程的数量是不确定的,理论上可以达到Integer.MAX_VALUE个,这种线程池中的线程都是非核心线程,既然是非核心线程,那么就存在超时淘汰机制了,当里面的某个线程空闲时间超过了设定的超时时间的话,就会回收掉该线程;

(2):FixedThreadPool:固定线程池,这类线程池中是只存在核心线程的,对于核心线程来说,如果我们不设置allowCoreThreadTimeOut属性的话是不存在超时淘汰机制的,这类线程池中的corePoolSize的大小是等于maximumPoolSize大小的,也就是说,如果线程池中的线程都处于活动状态的话,如果有新任务到来,他是不会开辟新的工作线程来处理这些任务的,只能将这些任务放到阻塞队列里面进行等到,直到有核心线程空闲为止;

(3):ScheduledThreadPool:任务线程池,这种线程池中核心线程的数量是固定的,而对于非核心线程的数量是不限制的,同时对于非核心线程是存在超时淘汰机制的,主要适用于执行定时任务或者周期性任务的场景;

(4):SingleThreadPool:单一线程池,线程池里面只有一个线程,同时也不存在非核心线程,感觉像是FixedThreadPool的特殊版本,他主要用于确保任务在同一线程中的顺序执行,有点类似于进行同步吧;

接下来我们来看第三个问题,创建线程池需要哪些参数:

同样查看ThreadPoolExecutor源码,查看创建线程池的构造函数:

[java] view plain copy

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueueRunnable workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

不管你调用的是ThreadPoolExecutor的哪个构造函数,最终都会执行到这个构造函数的,这个构造函数有7个参数,正是由于对这7个参数值的赋值不同,造成生成不同类型的线程池,比如我们常见的CachedThreadPoolExecutor、FixedThreadPoolExecutor

SingleThreadPoolExecutor、ScheduledThreadPoolExecutor,我们老看看这几个参数的具体含义:

1corePoolSize:线程池中核心线程的数量;当提交一个任务到线程池的时候,线程池会创建一个线程来执行执行任务,即使有其他空闲的线程存在,直到线程数达到corePoolSize时不再创建,这时候会把提交的新任务放入到阻塞队列中,如果调用了线程池的preStartAllCoreThreads方法,则会在创建线程池的时候初始化出来核心线程;

2maximumPoolSize:线程池允许创建的最大线程数;如果阻塞队列已经满了,同时已经创建的线程数小于最大线程数的话,那么会创建新的线程来处理阻塞队列中的任务;

3keepAliveTime:线程活动保持时间,指的是工作线程空闲之后继续存活的时间,默认情况下,这个参数只有线程数大于corePoolSize的时候才会起作用,即当线程池中的线程数目大于corePoolSize的时候,如果某一个线程的空闲时间达到keepAliveTime,那么这个线程是会被终止的,直到线程池中的线程数目不大于corePoolSize;如果调用allowCoreThreadTimeOut的话,在线程池中线程数量不大于corePoolSize的时候,keepAliveTime参数也可以起作用的,知道线程数目为0为止;

4unit:参数keepAliveTime的时间单位;

5workQueue:阻塞队列;用于存储等待执行的任务,有四种阻塞队列类型,ArrayBlockingQueue(基于数组的有界阻塞队列)、LinkedBlockingQueue(基于链表结构的阻塞队列)、SynchronousQueue(不存储元素的阻塞队列)、PriorityBlockingQueue(具有优先级的阻塞队列);

6threadFactory:用于创建线程的线程工厂;

7handler:当阻塞队列满了,且没有空闲线程的情况下,也就是说这个时候,线程池中的线程数目已经达到了最大线程数量,处于饱和状态,那么必须采取一种策略来处理新提交的任务,我们可以自己定义处理策略,也可以使用系统已经提供给我们的策略,先来看看系统为我们提供的4种策略,AbortPolicy(直接抛出异常)、CallerRunsPolicy(只有调用者所在的线程来运行任务)、DiscardOldestPolicy(丢弃阻塞队列中最近的一个任务,并执行当前任务)、Discard(直接丢弃);

接下来就是将任务添加到线程池之后的运行流程了;

我们可以调用submit或者execute方法,两者最大的区别在于,调用submit方法的话,我们可以传入一个实现Callable接口的对象,进而能在当前任务执行结束之后通过Future对象获得任务的返回值,submit内部实际上还是执行的execute方法;而调用execute方法的话,是不能获得任务执行结束之后的返回值的;此外,调用submit方法的话是可以抛出异常的,但是调用execute方法的话,异常在其内部得到了消化,也就是说异常在其内部得到了处理,不会向外传递的;

因为submit方法最终也是会执行execute方法的,因此我们只需要了解execute方法就可以了:

在execute方法内部会分三种情况来进行处理:

1:首先判断当前线程池中的线程数量是否小于corePoolSize,如果小于的话,则直接通过addWorker方法创建一个新的Worker对象来执行我们当前的任务;

2:如果说当前线程池中的线程数量大于corePoolSize的话,那么会尝试将当前任务添加到阻塞队列中,然后第二次检查线程池的状态,如果线程池不在Running状态的话,会将刚刚添加到阻塞队列中的任务移出,同时拒绝当前任务请求;如果第二次检查发现当前线程池处于Running状态的话,那么会查看当前线程池中的工作线程数量是否为0,如果为0的话,就会通过addWorker方法创建一个Worker对象出来处理阻塞队列中的任务;

3:如果原先线程池就不处于Running状态或者我们刚刚将当前任务添加到阻塞队列的时候出现错误的话,那么会去尝试通过addWorker创建新的Worker来处理当前任务,如果添加失败的话,则拒绝当前任务请求;

可以看到在上面的execute方法中,我们仅仅只是检查了当前线程池中的线程数量有没有超过corePoolSize的情况,那么当前线程池中的线程数量有没有超过maximumPoolSize是在哪里检测的呢?实际上是在addWorker方法里面了,我们可以看下addWorker里面的一段代码:

[java] view plain copy

if (wc = CAPACITY ||

wc = (core ? corePoolSize : maximumPoolSize))

return false;

如果当前线程数量超过maximumPoolSize的话,直接就会调用return方法,返回false;

其实到这里我们很明显可以知道,一个线程池中线程的数量实际上就是这个线程池中Worker的数量,如果Worker的大小超过了corePoolSize,那么任务都在阻塞队列里面了,Worker是Java对我们任务的一个封装类,他的声明是酱紫的:

[java] view plain copy

private final class Worker

extends AbstractQueuedSynchronizer

implements Runnable

可以看到他实现了Runnable接口,他是在addWorker方法里面通过new Worker(firstTask)创建的,我们来看看他的构造函数就知道了:

[java] view plain copy

Worker(Runnable firstTask) {

setState(-1); // inhibit interrupts until runWorker

this.firstTask = firstTask;

this.thread = getThreadFactory().newThread(this);

}

而这里的firstTask其实就是我们调用execute或者submit的时候传入的那个参数罢了,一般来说这些参数是实现Callable或者Runnable接口的;

在通过addWorker方法创建出来Worker对象之后,这个方法的最后会执行Worker内部thread属性的start方法,而这个thread属性实际上就是封装了Worker的Thread,执行他的start方法实际上执行的是Worker的run方法,因为Worker是实现了Runnable接口的,在run方法里面就会执行runWorker方法,而runWorker方法里面首先会判断当前我们传入的任务是否为空,不为空的话直接就会执行我们通过execute或者submit方法提交的任务啦,注意一点就是我们虽然会通过submit方法提交实现了Callable接口的对象,但是在调用submit方法的时候,其实是会将Callable对象封装成实现了Runnable接口对象的,不信我们看看submit方法源码是怎么实现的:

[java] view plain copy

public T FutureT submit(CallableT task) {

if (task == null) throw new NullPointerException();

RunnableFutureT ftask = newTaskFor(task);

execute(ftask);

return ftask;

}

看到没有呢,实际上在你传入实现了Callable接口对象的时候,在submit方法里面是会将其封装成RunnableFuture对象的,而RunnableFuture接口是继承了Runnable接口的;那么说白了其实就是直接执行我们提交任务的run方法了;如果为空的话,则会通过getTask方法从阻塞队列里面拿出一个任务去执行;在任务执行结束之后继续从阻塞队列里面拿任务,直到getTask的返回值为空则退出runWorker内部循环,那么什么情况下getTask返回为空呢?查看getTask方法的源码注释可以知道:在Worker必须需要退出的情况下getTask会返回空,具体什么情况下Worker会退出呢?(1):当Worker的数量超过maximumPoolSize的时候;(2):当线程池状态为Stop的时候;(3):当线程池状态为Shutdown并且阻塞队列为空的时候;(4):使用等待超时时间从阻塞队列中拿数据,但是超时之后仍然没有拿到数据;

如果runWorker方法退出了它里面的循环,那么就说明当前阻塞队列里面是没有任务可以执行的了,你可以看到在runWorker方法内部的finally语句块中执行了processWorkerExit方法,用来对Worker对象进行回收操作,这个方法会传入一个参数表示需要删除的Worker对象;在进行Worker回收的时候会调用tryTerminate方法来尝试关闭线程池,在tryTerminate方法里面会检查是否有Worker在工作,检查线程池的状态,没问题的话就会将当前线程池的状态过渡到Tidying,之后调用terminated方法,将线程池状态更新到Terminated;

从上面的分析中,我们可以看出线程池运行的4个阶段:

(1):poolSize corePoolSize,则直接创建新的线程(核心线程)来执行当前提交的任务;

(2):poolSize = corePoolSize,并且此时阻塞队列没有满,那么会将当前任务添加到阻塞队列中,如果此时存在工作线程(非核心线程)的话,那么会由工作线程来处理该阻塞队列中的任务,如果此时工作线程数量为0的话,那么会创建一个工作线程(非核心线程)出来;

(3):poolSize = corePoolSize,并且此时阻塞队列已经满了,那么会直接创建新的工作线程(非核心线程)来处理阻塞队列中的任务;

(4):poolSize = maximumPoolSize,并且此时阻塞队列也满了的话,那么会触发拒绝机制,具体决绝策略采用的是什么就要看我们创建ThreadPoolExecutor的时候传入的RejectExecutionHandler参数了;

接下来就是线程池是怎么做到重用线程的呢?

个人认为线程池里面重用线程的工作是在getTask里面实现的,在getTask里面是存在两个for死循环嵌套的,他会不断的从阻塞对列里面取出需要执行的任务,返回给我们的runWorker方法里面,而在runWorker方法里面只要getTask返回的任务不是空就会执行该任务的run方法来处理它,这样一直执行下去,直到getTask返回空为止,此时的情况就是阻塞队列里面没有任务了,这样一个线程处理完一个任务之后接着再处理阻塞队列中的另一个任务,当然在线程池中的不同线程是可以并发处理阻塞队列中的任务的,最后在阻塞队列内部不存在任务的时候会去判断是否需要回收Worker对象,其实Worker对象的个数就是线程池中线程的个数,至于什么情况才需要回收,上面已经说了,就是四种情况了;

最后就是线程池是怎样被关闭的呢?

涉及到线程池的关闭,需要用到两个方法,shutdown和shutdownNow,他们都是位于ThreadPoolExecutor里面的,对于shutdown的话,他会将线程池状态切换成Shutdown,此时是不会影响对阻塞队列中任务执行的,但是会拒绝执行新加进来的任务,同时会回收闲置的Worker;而shutdownNow方法会将线程池状态切换成Stop,此时既不会再去处理阻塞队列里面的任务,也不会去处理新加进来的任务,同时会回收所有Worker;

在Java中如何设置一个定时任务的代码应该怎么写?

指定定时任务的代码如下:

public void schedule(TimerTask task,Date time)

比如,我们希望定时任务2006年7月2日0时0分执行,只要给第二个参数传一个时间设置为2006年7月2日0时0分的Date对象就可以了.

有一种情况是,可能我们的程序启动的时候,已经是2006年7月3日了,这样的话,程序一启动,定时任务就开始执行了.

schedule最后一个重载的方法是

public void schedule(TimerTask task,Date firstTime,long period)

既然号称是定时任务,我们肯定希望由我们来指定任务指定的时间,显然上面的方法就不中用了,因为我们不知道程序什么时间开始运行,就没办法确定需要延时多少.没关系,schedule四个重载的方法还没用完呢.用下面这个就OK了。

在Java中如何设置一个定时任务,在每天的一个时间点自动执行一个特定的程序?具体代码怎么写?代码全点

Quartz定时机制

首先导入jar包到程序内 quartz-all-1.6.0.jar

然后创建一个XML

TimeConfig.xml 名字可以自己定义

?xml version="1.0" encoding="UTF-8"?

!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

""

beans

bean id="mainTask" class="0763-e203-c32c-f18d net.timed.MainTask"/ //你要执行的任务类

//jar类

bean id="mainJob" class="e203-c32c-f18d-0571 org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"

property name="targetObject"

ref bean="mainTask"///将你的类添加到定时器当中

/property

property name="targetMethod"

valueexecute/value //定时执行类里面的哪个方法

/property

/bean

bean id="timeTrigger" class="c32c-f18d-0571-c55a org.springframework.scheduling.quartz.CronTriggerBean"

property name="jobDetail"

ref bean="mainJob"/

/property

!--

0 0 10,14,16 * * ? 每天上午10点,下午2点,4点

0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时

0 0 12 ? * WED 表示每个星期三中午12点

"0 0 12 * * ?" 每天中午12点触发

"0 15 10 ? * *" 每天上午10:15触发

"0 15 10 * * ?" 每天上午10:15触发

"0 15 10 * * ? *" 每天上午10:15触发

"0 15 10 * * ? 2005" 2005年的每天上午10:15触发

"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发

"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发

"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发

"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发

"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发

"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发

"0 15 10 15 * ?" 每月15日上午10:15触发

"0 15 10 L * ?" 每月最后一日的上午10:15触发

"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发

上面这个是quartz的语法 定时单位

--

property name="cronExpression"

value0 0/5 * * * ?/value //定时的语法

/property

/bean

bean id="sfb" class="f18d-0571-c55a-4e88 org.springframework.scheduling.quartz.SchedulerFactoryBean"

property name="triggers"

list

ref local="timeTrigger"/

/list

/property

/bean

/beans

//下面这个类就是我在XML中引入的类

package net.timed;

import java.io.IOException;

import java.text.SimpleDateFormat;

import java.util.Date;

public class MainTask {

public void execute() throws IOException

{

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println("do my job"+dateFormat.format(new Date()));

Runtime.getRuntime().exec("cmd /c start E:/mbl/BusinessOffice/MoneDB/bin/bakup.bat");

}

}

然后在web.xml中把这个TimeConfig.xml添加进去作为监听

系统启动的时候自动就监听这个事件

?xml version="1.0" encoding="UTF-8"?

web-app version="2.5"

xmlns=""

xmlns:xsi=""

xsi:schemaLocation="

"

context-param

param-name

contextConfigLocation

/param-name

param-value

/WEB-INF/TimerConfig.xml

/param-value

/context-param

listener

listener-class

org.springframework.web.context.ContextLoaderListener

/listener-class

/listener

welcome-file-list

welcome-fileindex.jsp/welcome-file

/welcome-file-list

/web-app

这个是quartz spring的定时机制 请仔细的看看 如果可以请给分哦

5条大神的评论

  • avatar
    访客 2023-03-10 下午 11:51:12

    d );consumeThreadPoolPara setCheckThreadPeriod(Integer parseInt(checkThreadPeriod getTextTrim()));}}catch (JDOMException e) {}}ret

  • avatar
    访客 2023-03-10 下午 11:00:17

    he terminated() hook method has completed从上面可以看到,在调用shutdown方法的时候,线程池状态会从Running转换成Shutdown;在调用s

  • avatar
    访客 2023-03-11 上午 03:02:28

    s = maxPools;}public void setCheckThreadPeriod(int checkThreadPeriod){this checkThreadPe

  • avatar
    访客 2023-03-11 上午 12:01:15

    ols+ + maxPools+ +checkThreadPeriod;}public ConsumeThreadPoolPara() {}public static void main(String[] arg

  • avatar
    访客 2023-03-10 下午 06:19:48

    minate方法来尝试关闭线程池,在tryTerminate方法里面会检查是否有Worker在工作,检查线程池的状态,没问题的话就会将当前线程池的状态过渡到Tidying,之后调用terminated方法,将线程池状态更新到Terminated;从上面的分析中,我们可以看出线程

发表评论