对于模糊的标题感到抱歉,但我不知道如何简洁地描述问题。
使用ScheduledExecutorService,我安排Runnable每5秒运行一次,没有初始延迟。我有一个shceduled任务,在60秒后调用ScheduledExecutorService上的shutdonw()。关闭发生时,主线程似乎停止。它没有退出。
在下面的代码中," Ping"每5秒从阻塞队列中正确拾取一次。当ScheduledExecutorService关闭时,它会停止打印" Ping",isDone()检查下面的行不会执行,测试结束时记录器也不会执行,但Eclipse会显示测试还在运行
"试验" (不测试任何东西,只使用它而不是main())
package scheduledExecutorTest;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.paul.scheduledexecutortest.service.HeartBeatService;
import com.paul.scheduledexecutortest.service.MasterScheduler;
public class SchedulerTest {
private Logger LOGGER = LoggerFactory.getLogger(SchedulerTest.class);
@Test
public void testScheduleTasks() throws InterruptedException {
MasterScheduler.scheduleToRunOnceWithInitialDelay(new Runnable() {
@Override
public void run() {
MasterScheduler.shutDown();
}
}, 60L);
HeartBeatService heartbeatService = new HeartBeatService();
heartbeatService.doStart();
LOGGER.debug("doStart() returned"); //THIS NEVER GETS HIT
}
}
计划心跳的心跳服务:
package com.paul.scheduledexecutortest.service;
import java.util.concurrent.ScheduledFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.paul.scheduledexecutortest.HeartBeat;
public class HeartBeatService {
private Logger LOGGER = LoggerFactory.getLogger(HeartBeatService.class);
public void doStart() throws InterruptedException {
Scheduler<String> scheduler = new Scheduler<String>();
ScheduledFuture<String> taskStatus = scheduler.scheduleToRunPeriodically(new HeartBeat(), 5L);
try {
while (taskStatus.isDone() == false) {
LOGGER.debug(scheduler.getTaskOutput());
}
}
catch (Exception ex) {
LOGGER.error("Something happened");
}
LOGGER.debug("COMPLETE"); //THIS NEVER GETS HIT
}
}
调度程序:
package com.paul.scheduledexecutortest.service;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ScheduledFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.paul.scheduledexecutortest.ScheduledTask;
public class Scheduler<T> {
private Logger LOGGER = LoggerFactory.getLogger(Scheduler.class);
private BlockingQueue<T> queue = new ArrayBlockingQueue<T>(1);
@SuppressWarnings("unchecked")
public ScheduledFuture<T> scheduleToRunPeriodically(ScheduledTask<T> scheduledTask,
long timeIntervalSeconds) {
Runnable task = transformIntoRunnable(scheduledTask);
return (ScheduledFuture<T>) MasterScheduler.scheduleToRunPeriodically(task,
timeIntervalSeconds);
}
@SuppressWarnings("unchecked")
public ScheduledFuture<T> scheduleToRunPeriodicallyWithInitialDelay(
ScheduledTask<T> scheduledTask, long repeatTimeIntervalSeconds,
long initalDelaySeconds) {
Runnable task = transformIntoRunnable(scheduledTask);
return (ScheduledFuture<T>) MasterScheduler.scheduleToRunPeriodicallyWithInitialDelay(task,
repeatTimeIntervalSeconds, initalDelaySeconds);
}
public void scheduleToRunOnceWithInitialDelay(ScheduledTask<T> scheduledTask,
long timeIntervalSeconds) {
Runnable task = transformIntoRunnable(scheduledTask);
MasterScheduler.scheduleToRunOnceWithInitialDelay(task, timeIntervalSeconds);
}
private Runnable transformIntoRunnable(final ScheduledTask<T> scheduledTask) {
LOGGER.debug("Converting ScheduledTask into Runnable");
return () -> queue.add(scheduledTask.invoke());
}
public T getTaskOutput() throws InterruptedException {
return queue.take();
}
}
Singleton Master Scheduler
package com.paul.scheduledexecutortest.service;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MasterScheduler {
private static Logger LOGGER = LoggerFactory.getLogger(MasterScheduler.class);
public static final int THREAD_POOL_SIZE = 10;
private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(THREAD_POOL_SIZE);
public static ScheduledFuture<?> scheduleToRunPeriodically(Runnable task, long timeIntervalSeconds) {
LOGGER.debug("Scheduling task to run async every " + timeIntervalSeconds + " seconds without delay");
return scheduler.scheduleAtFixedRate(task, 0, timeIntervalSeconds, TimeUnit.SECONDS);
}
public static ScheduledFuture<?> scheduleToRunPeriodicallyWithInitialDelay(Runnable task,
long repeatTimeIntervalSeconds, long initalDelaySeconds) {
LOGGER.debug("Seceduling task to run every " + repeatTimeIntervalSeconds + " seconds after initial delay of "
+ initalDelaySeconds + " seconds");
return scheduler.scheduleAtFixedRate(task, initalDelaySeconds, repeatTimeIntervalSeconds, TimeUnit.SECONDS);
}
public static void scheduleToRunOnceWithInitialDelay(Runnable task, long timeIntervalSeconds) {
scheduler.schedule(task, timeIntervalSeconds, TimeUnit.SECONDS);
}
public static void shutDown() {
System.err.println("SCHEDULER SHUTTING DOWN GRACEFULLY. NO NEW TASKS ALLOWED");
scheduler.shutdown();
}
}
Heatbeat(已安排的任务)
package com.paul.scheduledexecutortest;
public class HeartBeat implements ScheduledTask<String> {
@Override
public String invoke() {
return "Ping";
}
}
输出:
13:48:41.721 [main] DEBUG com.paul.scheduledexecutortest.service.Scheduler - Converting ScheduledTask into Runnable
13:48:41.780 [main] DEBUG com.paul.scheduledexecutortest.service.MasterScheduler - Scheduling task to run async every 5 without delay
13:48:41.781 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:48:46.807 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:48:51.782 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:48:56.782 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:01.782 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:06.783 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:11.783 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:16.783 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:21.784 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:26.783 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:31.783 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
13:49:36.783 [main] DEBUG com.paul.scheduledexecutortest.service.HeartBeatService - Ping
SCHEDULER SHUTTING DOWN GRACEFULLY. NO NEW TASKS ALLOWED
答案 0 :(得分:1)
似乎doStart()
方法阻止了,因为taskStatus.isDone()
几乎总是假的,请参阅this。
在Scheduler.java
课程中,为什么在只包含1个元素时需要阻塞队列?
我建议执行以下更改:
<强> Test.java:强>
MasterScheduler.scheduleToRunOnceWithInitialDelay(() -> MasterScheduler.shutDown(), 60L);
HeartBeatService heartbeatService = new HeartBeatService();
heartbeatService.doStart();
<强> HeartBeatService:强>
public void doStart() throws InterruptedException {
Scheduler<String> scheduler = new Scheduler<String>();
scheduler.scheduleToRunPeriodically(new HeartBeat(), 5L);
}
<强> Scheduler.java:强>
private Runnable transformIntoRunnable(final ScheduledTask<T> scheduledTask) {
LOGGER.debug("Converting ScheduledTask into Runnable");
return () -> LOGGER.debug((String)scheduledTask.invoke());
}
<强> MasterScheduler.java:强>
public static void shutDown() {
System.err.println("SCHEDULER SHUTTING DOWN GRACEFULLY. NO NEW TASKS ALLOWED");
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
}
}