Java 当我从未来获得结果时,什么是重新提交可调用文件的最佳方式?

Java 当我从未来获得结果时,什么是重新提交可调用文件的最佳方式?,java,concurrency,Java,Concurrency,有更好的方法吗?我宁愿使用j.u.c现有的框架,而不是滚动我自己的 请看run方法 我需要在将来获得结果后尽快重新提交Callable。 我使用这个单独的可运行线程,就是为了实现这一点,如下所示 虽然这应该可以编译,但它显然不是一段工作代码 public class ResubmitOnCompletion implements Runnable { private CompletionService<DeviceData> completionService;

有更好的方法吗?我宁愿使用j.u.c现有的框架,而不是滚动我自己的

请看run方法

我需要在将来获得结果后尽快重新提交Callable。 我使用这个单独的可运行线程,就是为了实现这一点,如下所示

虽然这应该可以编译,但它显然不是一段工作代码

public class ResubmitOnCompletion implements Runnable {

    private CompletionService<DeviceData> completionService;

    private ConcurrentHashMap<String, Device> devices;

    public void run() {

      //-- keep resubmitting the callable.
      while(true){


        try {
          //-- Get the returned data from completed job
          Future<DeviceData> f=null;
          DeviceData dd=null;

          f = completionService.take();

          //-- Get the completed job's data 
          dd=f.get();

          //-- now resubmit the job if device still is part of the active device collection
          completionService.submit((Callable<DeviceData>) devices.get(dd.getDeviceId()));
      }
      catch (CancellationException e) {
        e.printStackTrace();
      }
      catch (InterruptedException e) {
        e.printStackTrace();
      } catch (ExecutionException e) {
        e.printStackTrace();
      }         
    }   
  }


    //-- Device Data
    private class DeviceData {
      /**
       * Unique Device Identifier
       */
      private final String deviceId;

      /**
       * Holds all numeric data of the device.
       * Key=Variable id of the parameter
       * Value=Numeric value of the parameter
       */
      private final ConcurrentHashMap<String, BigDecimal> numericData;



      private DeviceData(String deviceId,
          ConcurrentHashMap<String, BigDecimal> numericData) {
        super();
        this.deviceId = deviceId;
        this.numericData = numericData;
      }


      /**
       * @return the deviceId
       */
      public String getDeviceId() {
        return deviceId;
      }

      /**
       * @return the numericData
       */
      public ConcurrentHashMap<String, BigDecimal> getNumericData() {
        return numericData;
      }
    }   

    //-- Device
    private class Device {
      public DeviceData call() throws Exception {
        return new DeviceData("",new ConcurrentHashMap<String, BigDecimal>());
      }

    }
}

我不认为ExecutorService/CompletionService是您真正想要的。如果您希望作业继续,那么您确实有一个工作线程正在生成阻塞队列的结果


如果您需要限制在任何特定时间运行的线程数量,这是一个不同的问题,但目前您只需存储一个ConcurrentMap,生产者线程使用它将结果放入其中,消费者从中读取结果。

我认为ExecutorService/CompletionService不是您真正想要的。如果您希望作业继续,那么您确实有一个工作线程正在生成阻塞队列的结果


如果需要限制在不同关注点的任何特定时间运行的线程数,但目前,您只需存储一个ConcurrentMap,生产者线程使用它将结果放入其中,消费者从中读取结果。

为什么不让作业本身在结束时检查状态,并在必要时重新提交呢。只要您的执行者有一个无限制的队列,这将起作用。

为什么不让作业本身在结束时检查状态,并在必要时重新提交它自己呢。只要您的执行者有一个无限的队列,这就可以工作。

您只需提交Runnable,然后在运行中重新提交自己

ExecutorService e = Executors.newFixedThreadPool(1);

private void submitWork(){
   e.submit(new Runnable(){
       public void run(){
          ///do work with devices and get its data            
          e.submit(this);
       }
   });
}

我不确定这为什么不起作用。

您可以简单地提交Runnable,然后在运行中重新提交自己

ExecutorService e = Executors.newFixedThreadPool(1);

private void submitWork(){
   e.submit(new Runnable(){
       public void run(){
          ///do work with devices and get its data            
          e.submit(this);
       }
   });
}

我不确定这为什么行不通。

谢谢你的建议。我确实需要限制线程的数量。我的任务数大于线程数,因此为了使其可伸缩,我需要将completionService与Executor一起使用。您提供的解决方案是否可以扩展?如果可以,那么我可以改变我的方法。谢谢你的建议。我确实需要限制线程的数量。我的任务数大于线程数,因此为了使其可伸缩,我需要将completionService与Executor一起使用。您提供的解决方案是否可以扩展?如果可以的话,我可以改变我的方法。它应该会奏效。但是我可以从Callable重新提交而不是runnable吗?对不起,没有格式化。。worker.submitnew可调用{公共对象调用{//-Do work,get data,将其存储在某处对象数据=新对象;storeit.putid,data;//-resubmit worker.submitthis;//-return data忽略返回数据;}//-呼叫}//-callable;您要返回到哪里?这不起作用,因为您失去了未来和第一次调用后返回的值,正如我在回答中用相同的内容指出的那样,您需要注意您的执行器有一个无界队列,否则您可能会使执行器死锁。fixedThreadPool使用无界队列如果它是一个单线程池,并且您试图在其内部调用返回的将来的get,那么此时唯一可以死锁的方法是callable@Amit好的,我明白了。如果是这样的话,你不一定需要一个可调用的。你可以做你在评论中链接的事情,它应该工作得很好。但是从可读性的角度来看,它会ld可能会混淆人们为什么使用Callable而不需要它返回的未来。这就是为什么我建议RunnableIt应该工作。但是我可以从Callable重新提交而不是runnable吗?抱歉,没有格式化..worker.submitnew Callable{public Object call{//-Do work,get data,将其存储在某处对象数据=新对象;storeit.putid,data;//-resubmit worker.submitthis;//-return data忽略返回数据;}//-呼叫}//-callable;您要返回到哪里?这不起作用,因为您失去了未来和第一次调用后返回的值,正如我在回答中用相同的内容指出的那样,您需要注意您的执行器有一个无界队列,否则您可能会使执行器死锁。fixedThreadPool使用无界队列如果它是一个单线程池,并且您试图在其内部调用返回的将来的get,那么此时唯一可以死锁的方法是callable@Amit好的,我明白了。如果你是这样的话 不一定需要一个可调用的。你可以做你在评论中链接的事情,它应该可以正常工作。然而,从可读性的角度来看,它可能会让人们困惑,为什么您使用Callable而不需要它返回的未来。这就是我建议Runnable的原因