Java线程定时得到结果退出示例
rehoni / 2020-11-24
大致需求
定时每几秒调用一次rest接口,如果接口响应成功则退出线程,如果接口响应失败,则继续调用直至成功。
做了一个简单的线程任务。简单来说是一个异步的调用方式。目前采用的方式是设置一个flag,作为判断rest接口是否调用成功的结果标志位,接口调用不成功则线程死循环;接口调用成功则线程不进入while,退出。
public static void main(String[] args) {
// 线程沉睡时间,每3秒试图调用一次接口插入到告警表
final long timeInterval = 3000;
AtomicBoolean flag = new AtomicBoolean(false);
Thread thread = new Thread(() -> {
while (!flag.get()) {
flag.set(testFlag());
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
log.info("thread sleep interrupted");
}
}
});
thread.start();
}
private static boolean testFlag() {
int code = 500;
boolean fl = false;
try {
if (code == 500) {
throw new NullPointerException();
} else if (code == 200) {
log.info("code = 200,存入数据库");
fl = true;
}
} catch (Exception e) {
log.info("未获得code");
return false;
}
return fl;
}
Connected to the target VM, address: '127.0.0.1:51619', transport: 'socket'
15:38:56.445 [Thread-0] INFO com.nrec.pcs9000.app.task.RobotLinkageTask - 未获得code
15:38:59.450 [Thread-0] INFO com.nrec.pcs9000.app.task.RobotLinkageTask - 未获得code
15:39:02.451 [Thread-0] INFO com.nrec.pcs9000.app.task.RobotLinkageTask - 未获得code
15:39:05.452 [Thread-0] INFO com.nrec.pcs9000.app.task.RobotLinkageTask - 未获得code
15:39:08.453 [Thread-0] INFO com.nrec.pcs9000.app.task.RobotLinkageTask - 未获得code
15:39:25.722 [Thread-0] INFO com.nrec.pcs9000.app.task.RobotLinkageTask - code = 200,存入数据库
Disconnected from the target VM, address: '127.0.0.1:51619', transport: 'socket'
需求升级
在原有需求上考量,如果接口持续调用失败,那新开的线程则一直不会退出。一段时间内产生的线程要是足够多,说不定导致所有的线程不会退出,JVM宕机。因此在原有的基础上加一个固定的超时需求。
定时每几秒调用一次rest接口,如果接口响应成功则退出线程,如果接口响应失败,则继续调用直至成功。如果接口响应一直失败,则在固定的时间内超时退出。
// 线程沉睡时间,每6秒试图调用一次接口插入到告警表
ExecutorService executor = Executors.newSingleThreadExecutor();
final long timeInterval = 6000;
AtomicBoolean flag = new AtomicBoolean(false);
Future<Boolean> future = executor.submit(() -> {
while (!flag.get()) {
flag.set(getAndInsertTaskPatrolledId(headerParameters, taskCode, stationCode));
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
log.info("线程中断,退出");
return false;
}
}
// 注意这里也是false,退出while之后线程也是结束的
return false;
});
try {
log.info("开始获取机器人任务运行状态");
// 10分钟超时时间
future.get(600, TimeUnit.SECONDS);
log.info("获取机器人任务运行状态成功,已存入数据库!");
} catch (TimeoutException e) {
future.cancel(true);
log.info("线程超时结束!");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdownNow();