创建作业队列或任务控制器并在Java中动态添加任务到其中

问题描述 投票:0回答:3

我想创建一个作业队列来执行多个任务。但是,我的要求是我应该能够随时将任务添加到该作业队列中,并且所有这些任务都应该按顺序执行。我在网上搜索了一些解决方案,找到了这两个链接:

  1. Java 线程池执行器示例

  2. Java 执行器框架教程和最佳实践

但是我不能同时使用这两种解决方案。因为启动

ExecutorService
后我无法向服务添加新任务。因为我们知道它可能会抛出
InterruptedException
ConcurrentModificationException

java multithreading executorservice
3个回答
4
投票

您可以使用

BlockingQueue
在单独的线程中继续等待,直到出现一个或多个
Runnable

public class Mainer {
    private static final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(15);

    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (true) {
                try {
                    queue.take().run();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        t.start();

        for (int i = 0; i < 10; i++) {
            queue.add(() -> {
                System.out.println("Hello");
            });
        }
    }

}

4
投票

我认为您应该使用

ExecutorService

  • 它维护一个要运行的任务队列。如果需要,您可以提供自己的队列。
  • 可以使用
    submit
    方法随时添加新任务。
  • 提交任务即可获得期货
  • 任务可以一次运行一个,也可以使用一组工作线程并行运行。
  • 如果使用多线程,不同的执行器服务实现提供不同的池管理策略。
  • 有排空和关闭服务的操作。

如果您希望

ExecutorService
始终一次运行一个任务,请确保指定最大大小为一个线程的线程池。

请提供一些示例链接

javadocs 有示例。


您提出的反对意见均基于不正确的信息。

  1. 但是我不能同时使用这两种解决方案。因为启动后
    ExecutorService
    我无法向服务添加新任务。

是的,你可以。这就是

ExecutorService.submit(...)
的作用。

  1. 因为我们知道它可能会抛出
    InterruptedException
    ...

仅当您的应用程序执行某些操作导致发生这种情况时,它才会抛出

InterruptedException
;例如使用
ExecutorService
关闭
shutdownNow()
。 (如果您不想这样做,可以使用
shutdown()
代替,或者根本不关闭执行器。有关更多详细信息,请参阅 javadocs。)

无论如何,您的代码可以处理异常,就像其他答案中的代码一样......尽管它以您不应该在生产代码中执行的方式处理异常。 (将堆栈跟踪打印到标准输出是一个坏主意。在某些情况下,忽略

InterruptedException
可能是错误的事情。)

  1. ... 或
    ConcurrentModificationException
    .

AFAIK,

ExecutorService
可能抛出
ConcurrentModificationException
的唯一情况是,如果您使用未正确实现的自定义
Queue
类。


0
投票

将实施添加到Stephen回答

public class MyController {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Logger logger = Logger.getLogger(MyController.class.getName());

    //POST
    public void addTask(String taskId){
        Runnable task = createTask(taskId);
        executor.submit(task);
    }

    public void shutdown(){
        executor.shutdown();
    }

    private Runnable createTask(String taskId) {
        return new Runnable() {
            @Override
            public void run() {
                try {
                    taskId.toString();
                    //your task
                }catch (Exception e){
                    logger.log(Level.SEVERE,"error executing task"+taskId);
                }
            }
        };
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.