线程在与Scheduler一起使用时进入同步块

时间:2014-09-25 12:12:55

标签: java multithreading quartz-scheduler synchronized

我正在尝试进行作业调度..虽然调度程序本身运行良好,但我想使用一个synchronized块,这样就不会同时运行两个作业(因为会出现DB Access并发问题)。但不幸的是,等待工作没有在通知

上醒来

以下是使用的代码:用于作业监听器

public class SJobListener  implements JobListener {
    public static final String LISTENER_NAME = "SJobListener";
    ExecutingClass ec = new ExecutingClass ();
    @Override
    public String getName() {
        return LISTENER_NAME; //must return a name
    }

    // Run this if job is about to be executed.
    @Override
    public  void jobToBeExecuted(JobExecutionContext context) {

        String jobName = context.getJobDetail().getKey().toString();
        System.out.println("jobToBeExecuted");
        System.out.println("Listener : Job : " + jobName + " is going to start...");
        System.out.println("Thread running in jobToBeExecuted :"+Thread.currentThread().getName()+" "+Thread.currentThread().getId());

        synchronized (ec) {
            System.out.println(Thread.currentThread().getName());
            System.out.println("SYNCHRONIZED BLOCK"+jobName);   
            if(!condition){
            try {
                System.out.println("Going to Wait");
                Thread.currentThread().wait(200);
                //check the condition again
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }
            //ec .execute(context); as scheduler automatically calls this method, explicitly calling it runs the method twice , one by scheduler and the other executed explicitly
                }

        //}


    //Run this after job has been executed
    @Override
    public  void jobWasExecuted(JobExecutionContext context,
            JobExecutionException jobException) {
        System.out.println("jobWasExecuted");

        String jobName = context.getJobDetail().getKey().toString();
        System.out.println("Listener :Job : " + jobName + " is finished...");
        System.out.println("Thread running in jobWasExecuted :"+Thread.currentThread().getName()+" "+Thread.currentThread().getId());

        /*String testCaseName = context.getJobDetail().getDescription();
          QueryBuilderUtil.updateRecordInSchedular(testCaseName,"completed");*/
        if (!jobException.getMessage().equals("")) {
            System.out.println("Exception thrown by: " + jobName
                + " Exception: " + jobException.getMessage());
            jobException.printStackTrace();
        }
        Thread.currentThread().notifyAll();

    }

以下是ExecutingClass的代码

public class ExecutingClass implements Job{
    private MyClass mc = new MyClass();

    public synchronized void execute(JobExecutionContext context) {     
        try
        {

            System.out.println("--------execute------ "+context.getJobDetail().getKey());
            System.out.println("--------Current Thread------ "+Thread.currentThread().getName()+" "+Thread.currentThread().getId());

                mc .executeMethod( );
                System.out.println("Done MyClass.executeTestCase");


        }
            catch (BusinessException e) {

        }       
    } 


    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

以下是MyClass的代码

public class MyClass(){

public synchronized void executeMethod( ){
//does the actual processing i.e read write from DB
}
}

问题是......之后的线程会等待,但是通知并不会使作业运行..或者通知不起作用..我不知道......有什么不对......等待线程永远不会完成它的工作。 。 感谢

1 个答案:

答案 0 :(得分:0)

看看这段代码:

new MyClass().executeMethod( ) 

现在即使你已经将executeMethod声明为synchronized,它也没有任何意义。那是因为Java锁(对于synchronized块)是特定于对象的。因此,使用相同MyClass实例的2个线程将阻塞,但如果每个线程都有一个新的MyClass实例要处理,则它们不会。

所以用

之类的东西替换新的MyClass()。executeMethod()

MyClass myClass = new MyClass(); //在代码中只创建一次

每个帖子应该使用:

myClass.executeMethod()

这将有助于同步线程。

这段代码也是如此:

ExecutingClass ec = new ExecutingClass ();

即使ExecutingClass的execute方法是同步的,它也无助于任何同步,因为每个线程都有自己的ExecutingClass实例来处理。如果要进行同步,请在线程之间共享对象实例。