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