[英]Thread safety issue while timing out the thread for each bundle
我正在一个项目中,我将具有不同的包/模型。 让我们举个例子,假设我有4个捆绑包,每个捆绑包都有一个方法名process
。
以下是我应该做的事情-
process method
,并且每个bundle中的process method
将返回一个映射,然后将该映射写入同一线程中或执行最佳方法的数据库中(我不确定在这是正确的方法)。 我所做的以下尝试很可能是有缺陷的,错误处理绝不是完整的。 有人可以指导我在错误处理案例中应该做什么吗?
下面是我的方法,它将以多线程方式调用所有捆绑包的process method
。
public void processEvents(final Map<String, Object> eventData) {
ExecutorService pool = Executors.newFixedThreadPool(5);
List<ProcessBundleHolderEntry> entries = new ArrayList<ProcessBundleHolderEntry>();
Map<String, String> outputs = (Map<String, String>)eventData.get(BConstants.EVENT_HOLDER);
for (BundleRegistration.BundlesHolderEntry entry : BundleRegistration.getInstance()) {
ProcessBundleHolderEntry processBundleHolderEntry = new ProcessBundleHolderEntry(entry, outputs);
entries.add(processBundleHolderEntry);
}
try {
List<Future<Object>> futures = pool.invokeAll(entries, 30, TimeUnit.SECONDS);
for (int i = 0; i < futures.size(); i++) {
// This works since the list of future objects are in the
// same sequential order as the list of entries
Future<Object> future = futures.get(i);
ProcessBundleHolderEntry entry = entries.get(i);
if (!future.isDone()) {
// log error for this entry
}
}
} catch (InterruptedException e) {
// handle this exception!
}
}
其次,为您的线程实现Callable的实现:
public class ProcessBundleHolderEntry implements Callable {
private BundleRegistration.BundlesHolderEntry entry;
private Map<String, String> outputs;
public ProcessBundleHolderEntry(BundleRegistration.BundlesHolderEntry entry, Map<String, String> outputs) {
this.entry = entry;
this.outputs = outputs;
}
public Object call() throws Exception {
final Map<String, String> response = entry.getPlugin().process(outputs);
// write to the database.
System.out.println(response);
return response;
}
}
谁能告诉我上述方法是否有问题,或者有没有更好,更有效的方法来做同样的事情? 我不确定是否也存在线程安全问题。
任何帮助将不胜感激。
您代码中唯一的共享对象是eventData
:只要在运行此方法时未对其进行修改(或者如果地图及其内容是线程安全的并且更改被安全地发布),则应该没问题。
关于任务的异常处理,通常需要执行以下操作:
try {
future.get();
} catch (ExecutionException e) {
Throwable exceptionInFuture = e.getCause();
//throw, log or whatever is appropriate
}
关于被中断的异常:这意味着您正在其中执行该方法的线程已被中断。 您需要执行的操作取决于您的用例,但通常应该停止正在执行的操作,例如:
} catch (InterruptedException e) {
pool.shutdownNow(); //cancels the tasks
//restore interrupted flag and exit
Thread.currentThread.interrupt();
//or rethrow the exception
throw e;
}
注意:线程池的用途是可重用的-您应该将执行程序服务声明为(私有最终)实例变量,而不是每次调用processEvents
方法时都创建一个实例变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.