Java 共享对象的等待/通知导致主线程挂起
首先,让我承认,我是一名经验丰富的Java开发人员,能够意识到等待/通知问题,但一直没有得到线索,这就是为什么当我们陷入某些问题而忽略了显而易见的问题时,我觉得更多的人的输入会有所帮助。我正在编写一个测试来验证Quartz作业类,我按照以下示例进行测试:Java 共享对象的等待/通知导致主线程挂起,java,multithreading,quartz-scheduler,Java,Multithreading,Quartz Scheduler,首先,让我承认,我是一名经验丰富的Java开发人员,能够意识到等待/通知问题,但一直没有得到线索,这就是为什么当我们陷入某些问题而忽略了显而易见的问题时,我觉得更多的人的输入会有所帮助。我正在编写一个测试来验证Quartz作业类,我按照以下示例进行测试: public class SchedulerTest { private static final Object LOCK = new Object(); @Test public void sh
public class SchedulerTest {
private static final Object LOCK = new Object();
@Test
public void shouldValidateSomethingInJob() {
Object[] paramsForTesting = ...
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
...
CustomJobListenerSupport jobListener =
new CustomJobListenerSupport(LOCK, paramsForTesting);
scheduler.getListenerManager().addJobListener(jobListener,
KeyMatcher.keyEquals(jobKey));
scheduler.start();
// synchronized (LOCK) {
// // Wait for scheduler to end to avoid DB rollback before that
// LOCK.wait();
// }
}
private static class CustomJobListenerSupport extends JobListenerSupport
{
private final Object lock;
public CustomJobListenerSupport(Object lock, Object ... paramsForTesting) {
...;
this.lock = lock;
}
@Override
public String getName() {
return "TestJobListener";
}
@Override
public void jobWasExecuted(JobExecutionContext context,
JobExecutionException jobException) {
if (isNotBlank(jobException.getMessage())) {
try {
cleanup(context.getScheduler());
} catch (SchedulerException e) {
logger.error(e);
}
throw new RuntimeException(jobException);
}
performAssertions();
try {
cleanup(context.getScheduler());
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
}
private void performAssertions() {
// Some assertions
}
@SneakyThrows
private void cleanup(Scheduler scheduler) throws SchedulerException {
scheduler.clear();
scheduler.shutdown();
System.out.println("\nLock in cleanup: "+lock);
synchronized (lock) {
lock.notify();
}
}
}
}
现在,在注释掉等待代码后,测试完成但失败,因为DB更改在调度程序完成之前回滚,如果我等待,主线程似乎至少会挂起,这花费了很长时间,似乎没有结束,我无法确定作业是否仍在运行,因为Junit没有编写包含日志语句的HTML报告。调试语句表明这两个类使用同一个锁对象。同意有比使用普通对象来锁定更好的选项,但我不熟悉ReentrantLock之类的类,所以希望稍后尝试
任何指示都会有很大帮助
谢谢,
Paddy使用调试器,检查是否调用了清理方法,以及是否执行了lock.notify。它可能应该在finally块中的某个位置,以确保它始终被执行,不管发生什么。可能在等待之前调用notify。添加检查是否已调用notify的标志。您好,我对其进行了调试,发现奇怪的是,当我注释等待部分时,程序到达作业调用的服务类,或者换句话说,作业运行,但当我等待时,它从未触发。调度程序应该是一个单独的线程,为什么在主线程进入等待队列时从不调用它?这令人费解