我正在开展一个项目,我将在其中使用不同的Bundles。我们举一个例子,假设我有5个Bundle,每个bundle都有一个方法名process
。
以下是我应该做的事情 -
process
方法,然后写入数据库。我不确定这样做的正确方法是什么?我应该有五个帖吗?每个捆绑一个线程?但是在那种情况下会发生什么,假设我有50个捆绑,那么我将有50个线程?我所做的以下尝试很可能是有缺陷的,并且错误处理绝不是完整的。但不知何故,我总是在这一行得到错误 -
pool.invokeAll
错误是 -
The method invokeAll(Collection<? extends Callable<T>>, long, TimeUnit) in the type ExecutorService is not applicable for the arguments (List<ModelFramework.ProcessBundleHolderEntry>, int, TimeUnit)
下面是我的方法,它将以多线程方式调用所有包中的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 {
// somehow I always get an error at invokeAll method. Is there anything wrong?
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!
}
}
其次,我已经在ModelFramework类中添加了线程的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;
}
}
任何人都可以帮助我解决我得到的错误吗?还有人可以告诉我上述方法是否有任何问题,或者是否有更好,更有效的方法做同样的事情?
任何帮助都将受到赞赏。
答案 0 :(得分:1)
没关系,我发现了实际的问题
public class ProcessBundleHolderEntry implements Callable {
应定义为
public class ProcessBundleHolderEntry implements Callable<Object> {
以匹配以下声明中的Object
类型
List<Future<Object>> futures = pool.invokeAll(entries, 30, TimeUnit.SECONDS);
invokeAll方法的签名是
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
答案 1 :(得分:1)
我所做的以下尝试很可能是有缺陷的,并且错误处理绝不是完整的。但不知何故,我总是在这一行得到错误 -
如果您希望ProcessBundleHolderEntry
返回Callable<Object>
,我认为问题是invokeAll(...)
应该实施List<Future<Object>>
。我刚刚编译了你的代码,这解决了这个问题。
在我看来它应该实现Callable<Map<String, String>>
。然后call方法应该返回正确的类型:
public Map<String, String> call() throws Exception {
然后invokeAll(...)
方法会返回正确的List<Future<Map<String, String>>
。
另一个(尽管有点奇怪)想法是将this
退出call()
方法。拥有ProcessBundleHolderEntry implements Callable<ProcessBundleHolderEntry>
并在从this
返回call()
之前在条目中记录回复。然后,您无需对条目进行get(i)
以匹配它。然后在一个对象中有条目,输出和响应。