spring quartz使用多线程并发“陷阱”(转)

定义一个job:ranJob,设置每秒执行一次,设置不允许覆盖并发执行

    <bean id="rankJob" class="com.chinacache.www.logstat.job.RankJob" />
    <bean id="rankJobDetail"
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="rankJob" />
        <property name="targetMethod" value="execute" />
        <property name="concurrent" value="false" />
    </bean>
    <bean id="rankJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <property name="jobDetail" ref="rankJobDetail" />
        <!-- 单位 ms,半小时 1800000 ms -->
        <property name="repeatInterval" value="1000 />
    </bean>  

java 代码

public void execute() throws InterruptedException {
        System.out.println("Start job");
        ExecutorService exec = Executors.newFixedThreadPool(1);  

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("thread start");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("thread end");
            }
        });
        exec.execute(thread);
        exec.shutdown();
           while (!exec.isTerminated()) {
               // 等待所有子线程结束,才退出主线程
           }
        System.out.println("end job");
    }  

打印结果如下:

    Start job
    thread start
    thread end
    end job  

    Start job
    thread start
    thread end
    end job  

    Start job
    thread start
    thread end
    end job  

使用isTerminated()方法等多线程结束后在结束job;多线程任务派发结束后,要使用shutdown()方法顺序关闭线程(等待正在执行任务,不接受新任务)

定义一个job:ranJob,设置每秒执行一次,设置不允许覆盖并发执行

  1. <bean id="rankJob" class="com.chinacache.www.logstat.job.RankJob" />
  2. <bean id="rankJobDetail"
  3. class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  4. <property name="targetObject" ref="rankJob" />
  5. <property name="targetMethod" value="execute" />
  6. <property name="concurrent" value="<span style="color: #ff0000;"><strong>false</strong></span>" />
  7. </bean>
  8. <bean id="rankJobTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
  9. <property name="jobDetail" ref="rankJobDetail" />
  10. <!-- 单位 ms,半小时 1800000 ms -->
  11. <property name="repeatInterval" value="<span style="color: #ff0000;"><strong>1000</strong></span>" />
  12. </bean>

job代码:

  1. System.out.println("Start job");
  2. ExecutorService exec = Executors.newFixedThreadPool(1);
  3. Thread thread = new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. System.out.println("thread start");
  7. try {
  8. Thread.sleep(3000);
  9. } catch (InterruptedException e) {
  10. // TODO Auto-generated catch block
  11. e.printStackTrace();
  12. }
  13. System.out.println("thread end");
  14. }
  15. });
  16. exec.execute(thread);
  17. System.out.println("end job");

程序输出结果:

  1. Start job
  2. end job
  3. <span style="color: #ff0000;"><strong>thread start</strong></span>
  4. Start job
  5. end job
  6. thread start
  7. Start job
  8. end job
  9. thread start
  10. Start job
  11. end job
  12. thread start
  13. <strong><span style="color: #ff0000;">thread end</span></strong>

从结果可以看到,job的并发覆盖配置似乎根本没有生效,原因是:job没有关注多线程执行情况

修改job代码,添加如下代码在job访问最后,线程处理完job才结束,

  1. while (!exec.isTerminated()) {
  2. // 等待所有子线程结束,才退出主线程
  3. }

修改代码后程序结果:

  1. Start job
  2. thread start
  3. thread end

可以看到job始终没有结束,说明ExecutorService始终没有终止,看看文档,加入shutdonw()方法,job所有代码如下:

  1. public void execute() throws InterruptedException {
  2. System.out.println("Start job");
  3. ExecutorService exec = Executors.newFixedThreadPool(1);
  4. Thread thread = new Thread(new Runnable() {
  5. @Override
  6. public void run() {
  7. System.out.println("thread start");
  8. try {
  9. Thread.sleep(3000);
  10. } catch (InterruptedException e) {
  11. // TODO Auto-generated catch block
  12. e.printStackTrace();
  13. }
  14. System.out.println("thread end");
  15. }
  16. });
  17. exec.execute(thread);
  18. exec.shutdown();
  19. while (!exec.isTerminated()) {
  20. // 等待所有子线程结束,才退出主线程
  21. }
  22. System.out.println("end job");
  23. }

打印结果如下:

  1. Start job
  2. thread start
  3. thread end
  4. end job
  5. Start job
  6. thread start
  7. thread end
  8. end job
  9. Start job
  10. thread start
  11. thread end
  12. end job

OK,至此spring quartz多线程并发问题解决。回顾下,我们要使用isTerminated()方法等多线程结束后在结束job;多线程任务派发结束后,要使用shutdown()方法顺序关闭线程(等待正在执行任务,不接受新任务)

时间: 2024-10-13 21:44:35

spring quartz使用多线程并发“陷阱”(转)的相关文章

Spring+quartz 实现定时任务job集群配置

为什么要有集群定时任务? 因为如果多server都触发相同任务,又同时执行,那在99%的场景都是不适合的.比如银行每晚24:00都要汇总营业额.像下面3台server同时进行汇总,最终计算结果可能是真实结果的3倍,那对银行来说是无法想象的,完全不可接受. 集群定时任务工作原理 所以为了解决以上问题,每个server把将要及正在运行的job所有状态都即时同步到中央数据库,然后再次触发调用时从数据库中分析是否已有别的server正在运行相同job (同名同定时时间点的job属于相当job),如果相同

深入浅出 Java Concurrency (39): 并发总结 part 3 常见的并发陷阱

常见的并发陷阱 volatile volatile只能强调数据的可见性,并不能保证原子操作和线程安全,因此volatile不是万能的.参考指令重排序 volatile最常见于下面两种场景. a. 循环检测机制 volatile boolean done = false; while( ! done ){        dosomething();    } b. 单例模型 (http://www.blogjava.net/xylz/archive/2009/12/18/306622.html)

Spring Quartz实现任务调度

任务调度 在企业级应用中,经常会制定一些"计划任务",即在某个时间点做某件事情 核心是以时间为关注点,即在一个特定的时间点,系统执行指定的一个操作 任务调度涉及多线程并发.线程池维护.运行时间规则解析.运行现场的保护以恢复等方面 Quartz框架是一个开源的企业级任务调度服务,已经被作为任务调度的良好解决方案. Quartz框架核心 Quartz对任务调度进行了高度抽象,提出了3个核心概念,并在org.quartz包中通过接口和类进行了描述 任务:就是执行的工作内容.Quartz提供J

基于spring+quartz的分布式定时任务框架

http://www.cnblogs.com/aaronfeng/p/5537177.html 问题背景 我公司是一个快速发展的创业公司,目前有200人,主要业务是旅游和酒店相关的,应用迭代更新周期比较快,因此,开发人员花费了更多的时间去更=跟上迭代的步伐,而缺乏了对整个系统的把控 没有集群之前,公司定时任务的实现方式 在初期应用的访问量并不是那么大,一台服务器完全满足使用,应用中有很多定时任务需要执行 有了集群之后,公司定时任务实现的方式 随着用户的增加,访问量也就随之增加,一台服务器满足不了

Java 多线程并发编程面试笔录一览

知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run 方法 方式二:声明实现 Runnable 接口的类.该类然后实现 run 方法 推荐方式二,因为接口方式比继承方式更灵活,也减少程序间的耦合. 3.获取当前线程信息? Thread.currentThread() 4.线程的分类 线程分为守护线程.用户线程.线程初始化默认为用户线程. setDaemon(true) 将该线程标记为

Spring-batch学习总结(2)—Job,Flow创建及应用,多线程并发,决策器,监听器,参数

一.Job的创建及其应用1.Job flow的介绍:(1)状态机:例完成step1,是否继续完成step2,step3,我们就需要通过Job flow来控制(2)进行演示:使用next()方法来达到顺序执行step1,step2...的目的,再使用on(),to(),from()方法达到与next()方法同样的目的,再展示fail()方法和stopAndRestart()方法:例1:创建JobFlowDemoOne,以及三个Step使用next()让其顺序执行JobFlowDemOne: pac

8. 多线程并发扩展(杂七杂八)

本章内容: 1.死锁 2.多线程并发最佳实践(如何安全并发) 3.Spring与线程安全 4.HashMap与ConcurrentHashMap深入分析 一.死锁 1.产生必要条件 (1)互斥条件:进程要求对所分配的资源(如打印机)进?排他性控制,即在?段时间内某资源仅为?个进程所占有.此时若有其他进程请求该资源,则请求进程只能等待.?个资源每次只能被?个进程使?.独?桥每次只能通过?个?. (2)不剥夺条件:进程所获得的资源在未使?完毕之前,不能被其他进程强?夺?,即只能由获得该资源的进程??

Cocos2d-x优化中多线程并发访问

多线程并发访问在Cocos2d-x引擎中用的不是很多,这主要是因为中整个结构设计没有采用多线程.源自于Objective-C的Ref对象,需要使用AutoreleasePool进行内存管理,AutoreleasePool是非线程安全的,所有不推荐在子多线程中调用Ref对象的retain(). release()和autorelease()等函数.另外,OpenGL上下文对象也是不支持线程安全的.但是有的时候我们需要异步加载一些资源,例如:加载图片纹理.声音的预处理和网络请求数据等.如果是异步加载

简单的多线程并发同步演示

#include "stdafx.h"#include <iostream>#include <Windows.h>using namespace std;HANDLE hMutex;DWORD WINAPI Fun(LPVOID lp){    while(1){        WaitForSingleObject(hMutex,INFINITE);        cout<<"fun"<<endl;//如果不用信