[英]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.