【问题标题】:ExecutorService argument to SwingWorkerSwingWorker 的 ExecutorService 参数
【发布时间】:2018-11-23 10:26:37
【问题描述】:

我有一个扩展 SwingWorker 的抽象类,名为 FetchWorker,用于获取一些后台数据并修改为我的应用程序获取的数据。在我的FetchWorker 中是StatisticLayerController 的内部类。此 StatisticLayerController 由两个类扩展。我在FetchWorker 中初始化新线程以进行一些计算。我以前用TrackHistoryLayerController.的ExecutorService

如下:

public class TrackHistoryLayerController extends StatisticLayerController
{
   private final ExecutorService heatMapAdderExecutor;
   ...

   public AdsbFetchWorker(...)  extends FetchWorker
   {
      super(...);
   }

   @Override
   protected final List<ADSBTrack> doInBackground() throws Exception
   {
      filtered.forEach( track -> {
         this.heatMapAdderExecutor.submit( new HeatmapAdderHelper( ... ) );
      } );
      while ( this.latch.getCount() != 0 )
      {
         this.publishValue( ( int ) this.latch.getCount() );
      }
      this.latch.await();
      this.publishValue( ( int ) this.latch.getCount() );
      if ( this.createImage() )
      {
         this.placeImage();
      }
      return filtered;
   }
}

所以在这种情况下HeatMapAdderHelper 是我的助手线程,它为我做一些计算。一切正常,一切都很好。 但是现在我想多改变一点类结构,我想让我的Controllerabstract 并且我不再希望我的Worker 类成为一个内部类。


我的问题是,我不能(不应该)在 Worker 内创建 ExecutorService,因为每次调用事件时都会初始化工作程序。我唯一能做的就是将 ExecutorService 从Controller 作为参数传递给SwingWorker,但这是一个好习惯吗?提前谢谢你。

【问题讨论】:

  • 使用static 执行器还是单例实例?
  • @daniu 你的意思是在工人内部对吧?但是我不是为所有控制器都提供了一个 ExecutorService 吗?
  • 是的,你知道。但请记住,ExecutorService 是一个包装器,用于管理作为全局资源的线程;在全球范围内管理它们是有意义的(并且只有少数几个)。仅仅添加线程(或ExecutorServices,就此而言)不会神奇地获得更多性能。
  • @daniu 所以你的意思是每个Controller 都有ExecutorService 并没有比只有一个一个为我提供一些额外的性能> ExecutorService 为所有 Controllers?
  • 是的,这就是我要说的。拥有 4 个 ExecutorServices 和 1 个线程和 1 个 ExecutorService 和 1 个线程在性能方面基本相同 - 但是后者可能会更好地分配工作。

标签: java multithreading swing executorservice swingworker


【解决方案1】:

你当然也可以直接使用CompletableFuture提供的默认ExecutorService

filtered.forEach( track -> {
     CompletableFuture.runAsync(new HeatmapAdderHelper( ... ) );
  } );

顺便说一句,这个

  while ( this.latch.getCount() != 0 )
  {
     this.publishValue( ( int ) this.latch.getCount() );
  }
  this.latch.await();
  this.publishValue( ( int ) this.latch.getCount() );

看起来很狡猾...等待结果时的繁忙循环?另外,为什么你已经在循环中等待之后await 锁存器?假设闩锁是CountDownLatch

我敢肯定,如果您提供更多上下文,我们可以提供更好的整体解决方案。

看起来你可以做类似的事情

CompletableFuture<Void>[] futures = 
     filtered.stream().map(t -> new HeatmapAdderHelper(t))
                 .map(CompletableFuture::runAsync)
                 .toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).andThen(createImage());

或者CountDownLatch:

CountDownLatch latch = new CountDownLatch(filtered.size());
filtered.forEach(f -> {
    CompletableFuture.runAsync(new HeatmapAdderHelper(f))
                     .thenRun(latch::countDown);
});
latch.await();
createImage();

【讨论】:

  • 我觉得有点粗心没看到while-loop的问题,本来就是想查看进度的,谢谢指出,我会修改的。虽然我对CompletableFuture真的不熟悉,但其实我之前没用过。在这种情况下,它与 ExecutorService 有何不同?它有初始池大小吗?
  • @Bleach A CompletableFuture 是同时计算的结果;它实现了Future 接口(当您将submit() 一个Callable 转换为ExecutorService 时,您会得到其中一个接口。CompletableFuture#runAsync 几乎只是一种在后台运行某些东西而无需处理ExecutorService 管理线程。
  • 我按照你写的方式修改了我的代码。但是我注意到每次单击按钮进行计算时,只有一个线程在 JVM 中运行,就像this photo 中的照片一样,这正常吗?
  • @Bleach 我真的不能告诉你;您可能想了解其他线程为何处于休眠/锁定等原因。
猜你喜欢
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 1970-01-01
  • 2016-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多