【问题标题】:ThreadPoolTaskExecutor shutdown/re-run issueThreadPoolTask​​Executor 关闭/重新运行问题
【发布时间】:2016-03-29 23:07:12
【问题描述】:

我正在尝试使用 Spring 的“ThreadPoolTask​​Executor”实现多线程连续任务执行。

这是我的班级:

@Component
public class AsyncWorker implements Worker  {
    public int threadCount = 5;
    private ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

    @Async
    public void doWork(Runnable runnable){
        executor.initialize();
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setCorePoolSize(threadCount);
        executor.setMaxPoolSize(threadCount);
        executor.setQueueCapacity(0);
        executor.setThreadGroupName("A");

        for (int i=0;i<5;i++) {
            executor.submit(runnable);
        }
        System.out.println("Active threads: " +executor.getActiveCount());
    }

    @Async
    public void StopTasks(){
        executor.shutdown(); 
    }

用法:

@Controller
@RequestMapping("api/test")
public class SendController {

    ThreadPoolExecutor executor =  new ErrorReportingThreadPoolExecutor(5);

    @Autowired AsyncWorker worker;
    boolean IsRunning = true;

    @RequestMapping(value = "/start_new", method = RequestMethod.POST)
    public Callable<String> StartNewTask(@RequestBody LaunchSend sendobj) throws IOException, InterruptedException {

//      System.out.println(sendobj.getThreadsCount());
        Runnable runnable = () -> {
            while(IsRunning) {
                MyVoid();
           }
        };

        worker.doWork(runnable);

        return () -> "Callable result";
    }

    @RequestMapping(value = "/stop", method = RequestMethod.GET)
    public Callable<String> StopTasks()  {
        IsRunning =false;
        if(SecurityContextHolder.getContext().getAuthentication().getName() != null &&  SecurityContextHolder.getContext().getAuthentication().getName() != "anonymousUser") {
            worker.StopTasks();
            return () -> "Callable result good";
        }
        else { return () -> "Callable result bad";}
    }
}

主要问题是:

当我第一次发送启动请求时 - 一切正常(除非我没有看到组名称的变化(executor.setThreadGroupName("A")))。

但是,在我发送停止请求并再次发送启动请求后 - 执行程序不会启动任务。这是它的样子:

ThreadPoolTaskExecutor-4 Global iteration # 4
ThreadPoolTaskExecutor-2 Global iteration # 5
ThreadPoolTaskExecutor-5 Global iteration # 3
ThreadPoolTaskExecutor-3 Global iteration # 2
Active threads: 5
ThreadPoolTaskExecutor-1 Global iteration # 1
ThreadPoolTaskExecutor-2 Global iteration # 9
ThreadPoolTaskExecutor-3 Global iteration # 9
ThreadPoolTaskExecutor-5 Global iteration # 9
ThreadPoolTaskExecutor-4 Global iteration # 9
ThreadPoolTaskExecutor-1 Global iteration # 10
Active threads: 1

只显示“活动线程:1”。可能是什么问题?

顺便说一句,将来,我想为它创建的 ThreadGroup 设置自定义名称(从 POST 请求/Spring Security Context 传输的参数),然后能够以某个组名终止所有线程(组名将是 Spring Security启动线程的用户的用户名。)有可能吗?

【问题讨论】:

  • 仅供参考,将 boolean isRunnable 标记为 volatile,不要使用 != 运算符比较字符串,使用 equals() 方法

标签: java multithreading spring java.util.concurrent


【解决方案1】:

这可能是时间问题。尝试添加一个短暂的等待,例如

Thread.sleep(1000); 

就在之前

System.out.println("Active threads: " +executor.getActiveCount());

并尝试写出池大小(以确保池大小设置正确):

System.out.println("Active threads: " +executor.getPoolSize());

【讨论】:

  • MyVoid中有迭代器,如果是时间问题会显示迭代#
  • 这些是活动线程:5 和活动线程:1 之间的输出吗?然后就很奇怪了,因为 ThreadPoolTask​​Executor 编号不一样,这也意味着当前确实存在 5 个线程,而不是 1 个。
  • 好的,我已经明白了,但我想问的是,在您第二次调用该方法后,您提供的日志输出的哪几行打印出来了?在“活动线程:5”行之后?
  • 那还不是第一个电话。只是 MyVoid 只是只有这个输出,所以它看起来非常快。然后第二次运行“活动线程:1”出现
【解决方案2】:

一旦任务完成它们的工作,它们就不再存在了,您需要将它们重新提交到调度程序才能让它们再次运行。它们不会无限期地留在执行者中。

【讨论】:

  • 每次我向“/start_new”控制器发送请求时,worker.doWork(runnable);被调用,也就是重新提交它们,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-08
  • 2017-03-02
  • 2021-01-02
  • 2015-08-09
  • 1970-01-01
  • 2019-04-30
  • 1970-01-01
相关资源
最近更新 更多