ThreadPoolTaskScheduler 怎么用多线程去跑任务呢

2018-12-27 13:44:04 +08:00
 shayang888
@Autowired
private ThreadPoolTaskScheduler threadPoolTaskScheduler;

private ScheduledFuture<?> future;

@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
传任务的 id,然后开启对应的任务
public void taskStartService(int id){
        try {
            Optional<Task> taskOptional = taskRepository.findById(id);
            if (taskOptional.isPresent()) {
                future = threadPoolTaskScheduler.schedule(() -> {
                        System.out.println("task-" + id + ", " + Thread.currentThread().getName() + "-" + Thread.currentThread().getId());
                        threadMap.put(id, future);
                    }
                }, new CronTrigger(taskOptional.get().getTaskTime()));
    }

然后我启动了 2 个任务,打印出来确实 2 个任务都在运行,但是为什么线程打印出来只有 1 个线程在跑呢

task-1, threadPoolTaskScheduler-1-54
task-2, threadPoolTaskScheduler-1-54

实在是不会了,请大佬给点提示

4232 次点击
所在节点    Java
31 条回复
wccc
2018-12-27 15:52:00 +08:00
@Bean(destroyMethod = "shutdown")
public ThreadPoolTaskScheduler scheduledThreadPool() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("scheduled-thread-");
scheduler.setPoolSize(10);
//等待任务完成后关闭
scheduler.setWaitForTasksToCompleteOnShutdown(true);
//最多等待 60s
scheduler.setAwaitTerminationSeconds(60);
scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
scheduler.initialize();
return scheduler;
}
定义一个线程池
默认实现只有一个线程的线程池
shayang888
2018-12-27 16:25:42 +08:00
@wccc
你好,谢谢大佬,多个线程执行的问题我已经解决了,不过很奇怪为什么我在停止一个任务的时候 发现都停止了,然后我把 future 打印出来 发现是一摸一样的两个 task,这是怎么回事呢
```
task-2, threadPoolTaskScheduler-1-53, DelegatingErrorHandlingRunnable for com.apitest.service.TaskService$$Lambda$1086/0x0000000800a37840@3ebb0180
task-1, threadPoolTaskScheduler-2-78, DelegatingErrorHandlingRunnable for com.apitest.service.TaskService$$Lambda$1086/0x0000000800a37840@3ebb0180
```
这是我启动的两个任务,我在 startService 里打印了这两个 future 为什么这个值是一样的?,这样的话 我如果想停止某个任务,让另一个任务不受影响继续运行该怎么办了
wccc
2018-12-27 16:29:08 +08:00
建议打印 task 中执行日志
shayang888
2018-12-27 16:32:49 +08:00
@wccc
future = threadPoolTaskScheduler.schedule(() -> {
System.out.println("task-" + id + ", " + Thread.currentThread().getName() + "-" + Thread.currentThread().getId() + ", " + future);
}, new CronTrigger(taskOptional.get().getTaskTime()));
就是这样的,我打印 future 就得到的是一样的,这样我在调用 future.cancel()的时候 整个就停掉了,可是我只想停止单个的
wccc
2018-12-27 16:38:48 +08:00
不了解 ThreadPoolTaskScheduler 用于定时任务多线程的
多线程 线程池通常不用这个
shayang888
2018-12-27 16:40:10 +08:00
@wccc 确实 我现在就是需要创建不同 cron 的任务来独自运行 或者你有比较好的办法吗
wccc
2018-12-27 16:46:00 +08:00
mq 延时消息
kkjinping
2018-12-27 17:54:15 +08:00
默认 private volatile int poolSize = 1;
kkjinping
2018-12-27 17:55:27 +08:00
需要手动调用 setPoolSize(int size)
kkjinping
2018-12-27 18:00:54 +08:00
@shayang888 feature 会不会是因为并发导致的,打印出来的都是最后一个。
kkjinping
2018-12-27 18:02:13 +08:00
@shayang888 threadMap.put(id, future);放到 lambda 外面可以吗
kkjinping
2018-12-27 18:03:36 +08:00
@shayang888 private ScheduledFuture<?> future; 改成方法内局部变量应该也行
shayang888
2018-12-27 19:13:15 +08:00
@kkjinping 哇 谢谢大佬的回复 你有用过这个来做定时任务吗
shayang888
2018-12-27 19:16:34 +08:00
@kkjinping 放在局部里不行的 我这后面还有个 stopTaskService(int id) 是用来指定任务的停止的, 不过没按照我的需求生效我不知道为什么
public void taskStopService(int id){
if (taskRepository.findById(id).isPresent()) {
if (future != null) {
future.cancel(true);
}
}
DsuineGP
2018-12-28 10:06:22 +08:00
@shayang888 调用 future.cancel 只是向执行任务的线程发送中断指令,具体怎么响应这个指令需要在执行任务的线程中检测并作出相应的处理
kkjinping
2018-12-28 10:16:02 +08:00
@shayang888 threadMap.put(id, future); 你不是有这个吗,id 和 future 映射,那你关闭的时候就可以从 map 中拿到 future 了。所以可以把 future 放到局部变量。threadMap 是实例变量。
shayang888
2018-12-28 11:00:18 +08:00
@kkjinping 我这么做了 可是并没有用 拿到的 future 在 map 里显示出来是一摸一样的 future.cancel 就全给取消了
{1=DelegatingErrorHandlingRunnable for com.apitest.service.TaskService$$Lambda$1106/0x0000000800a92840@45f08f0a, 2=DelegatingErrorHandlingRunnable for com.apitest.service.TaskService$$Lambda$1106/0x0000000800a92840@45f08f0a}
你看,future 的值是一摸一样的
kkjinping
2018-12-28 11:56:27 +08:00
@shayang888 你有改成局部变量吗,future。要两部结合起来。future 放到局部变量。threadMap 是实例变量。
kkjinping
2018-12-28 11:56:56 +08:00
@shayang888 threadMap.put(id, future);还要放到 lambda 外面
kkjinping
2018-12-28 11:57:53 +08:00
Optional<Task> taskOptional = taskRepository.findById(id);
if (taskOptional.isPresent()) {
future = threadPoolTaskScheduler.schedule(() -> {
System.out.println("task-" + id + ", " + Thread.currentThread().getName() + "-" + Thread.currentThread().getId());

}
}, new CronTrigger(taskOptional.get().getTaskTime()));

threadMap.put(id, future);
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/521502

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX