【问题标题】:Customized ThreadPoolExecutor to execute some tasks concurrently and some in queue定制的 ThreadPoolExecutor 可以同时执行一些任务和队列中的一些任务
【发布时间】:2015-12-02 03:57:34
【问题描述】:

我正在使用 Java Swing 创建一个 MVP 应用程序。我需要执行各种Tasks,它们是Taskclass 的实例,我创建了扩展SwingWorker 类!

我遇到了Executors 类,但提供的执行器似乎都不能满足我的需求。

我想同时执行我的一些Task 实例和队列中的一些Task 实例。另外,我想要在所有任务完成后进行方法调用。比如,SwingWorker 类中的done 方法!

abstract class CustomExecutor extends ThreadPoolExecutor {

    CustomExecutor(Collection<Task> synchronousTasks, Collection<Task> asynchronousTasks) {
        // .........
    }

    // To be called when all tasks have been executed successfully!
    abstract void done();

}

我之前没用过ExecutorServiceThreadPoolExecutor,也想不出任何解决办法!

【问题讨论】:

  • “我想同步(并发)执行我的一些任务实例和异步(在队列中)执行我的一些任务实例。”是什么意思? “同步”与“并发”有很大不同,“异步”与排队无关。你能详细说明/提供一个例子吗?
  • 请原谅造成混乱!我已经编辑了这个问题!我需要一些任务“同时”执行,一些任务“在队列中(一个接一个)!

标签: java multithreading concurrency swingworker threadpoolexecutor


【解决方案1】:

让我们简单比较一下您提到的两个解决方案 - SwingWorkerExecutors 框架。这两种解决方案背后的总体思路是相似的,但根据用例的不同,一种可能比另一种更好。

SwingWorker

  • 异步执行doInBackground方法中实现的逻辑。
  • 你需要继承SwingWorker来实现逻辑
  • Event Dispatch Thread - publish()process()done()get/setProgress() 和一些属性更改侦听器支持方法中有一些有用的方法可以与 Swing 集成并更新 UI。
  • SwingWorker 的单个实例对应于单个任务
  • 当您调用 SwingWorker.execute() 时,工作实例在内部将 自身 作为任务 (Callable) 提交给 ExecutorService(准确地说是 ThreadPoolExecutor),以便逻辑doInBackground 方法中实现的在单独的线程中异步执行
  • 您曾经创建的所有SwingWorker 对象都使用ThreadPoolExecutor 的默认配置,隐藏在SwingWorker 类中。如果您想提供自己的ExecutorService 来执行SwingWorkers,您可以通过设置sun.awt.AppContext.getAppContext().put(SwingWorker.class, yourOwnExecutorService) 来实现。但是,正如我所说,您的应用程序中的所有 SwingWorkers 只能有一个全局 ExecutorService
  • 总结一下:SwingWorker 向您隐藏并发细节,但公开 API 以与 Swing UI 通信。如果您的任务首先需要在后台进行一些计算,然后更新 UI,请使用 SwingWorker
  • 更多关于Concurrency in Swing

执行者框架

  • 您可以完全控制 ExecutorService 配置 - Executors 类中有一些实用方法可以创建一些常用配置,或者您可以自己实例化 ThreadPoolExecutor
  • 该框架是通用的 - 它接受任何Runnable/Callable 任务,这些任务可以执行任何逻辑。 Swing 没有特别的支持。
  • 你需要自己shutdownExecutorService
  • 更多关于Executors Framework

如果我正确理解您的要求,您可能更喜欢使用ExecutorService 而不是SwingWorker,这样您就可以更好地控制并发性。将您想要排队的任务(即按顺序执行)提交给使用Executors#newSingleThreadExecutor() 创建的执行程序。对于要同时执行的任务,请使用不同的ExecutorService - 使用Executors#newCachedThreadPool()Executors#newFixedThreadPool(int) 或自定义ThreadPoolExecutor 创建。请参阅 Javadocs 以检查哪个最适合您的需求。

您可以使用ExecutorService#invokeAll() 一次提交多个任务并阻止直到它们完成,或者您可以在循环中调用ExecutorService#submit() 以在不阻塞的情况下一个一个地提交它们稍后在从submit() 获得的Future 上调用Future.get() 以阻塞直到执行完成。

一旦你在所有期货上调用了get()——包括那些对应于synchronousTasksasynchronousTasks的期货,你就知道一切都完成了,你可以调用你的done()方法。

如果您想了解更多信息,我建议您阅读 Javadocs 以及 SwingWorkerExecutorExecutorService 类的源代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    相关资源
    最近更新 更多