Java 如何以多线程方式调用不同类的同一方法
在我的两个类中,我有一个名为Java 如何以多线程方式调用不同类的同一方法,java,multithreading,threadpool,executorservice,blockingqueue,Java,Multithreading,Threadpool,Executorservice,Blockingqueue,在我的两个类中,我有一个名为process的方法,比如CLASS-a和CLASS-B。现在在下面的循环中,我依次调用我的两个类的process方法,它工作得很好,但这不是我想要的方式 for (ModuleRegistration.ModulesHolderEntry entry : ModuleRegistration.getInstance()) { final Map<String, String> response = entry.getPlugin().proces
process
的方法,比如CLASS-a和CLASS-B
。现在在下面的循环中,我依次调用我的两个类的process方法
,它工作得很好,但这不是我想要的方式
for (ModuleRegistration.ModulesHolderEntry entry : ModuleRegistration.getInstance()) {
final Map<String, String> response = entry.getPlugin().process(outputs);
// write to database
System.out.println(response);
}
但是如果我删除最后一行executor.waittermination(5,TimeUnit.MINUTES)代码>然后它开始正常运行,过了一段时间,我总是遇到这样的错误-
JVMDUMP006I Processing dump event "systhrow", detail "java/lang/OutOfMemoryError" - please wait.
JVMDUMP032I JVM requested Heap dump using 'S:\GitViews\Stream\goldseye\heapdump.20130827.142415.16456.0001.phd' in response to an event
JVMDUMP010I Heap dump written to S:\GitViews\Stream\goldseye\heapdump.20130827.142415.16456.0001.phd
JVMDUMP006I Processing dump event "systhrow", detail "java/lang/OutOfMemoryError" - please wait.
有人能帮我找出我上面代码中的问题和错误吗?如果我按顺序运行,则不会出现任何错误,而且运行良好
还有什么比我现在做的更好的方法吗?因为将来我可以有多个插件处理器,而不是两个。
我试图做的是——以多线程的方式调用两个类的process方法,然后将其写入数据库bcoz。我的process方法将返回一个映射
在此方面如有任何帮助,将不胜感激。。如果可能的话,我正在寻找一个可行的例子。谢谢你的帮助,好的,下面是我在上面建议的评论的一些代码。免责声明:我不确定它是否有效,甚至是否编译,或者它是否解决了问题。但我们的想法是控制取消过程,而不是依赖于future.cancel
,我怀疑这可能会导致问题
class CheckQueue implements Runnable {
private volatile boolean cancelled = false;
public void cancel() { cancelled = true; }
public void run() {
Map<String, String> map;
try {
while(!cancelled) {
// blocks until a map is available in the queue, or until interrupted
map = queue.take();
if (cancelled) break;
// write map to database
System.out.println(map);
} catch (InterruptedException e) {
}
while((map = queue.poll()) != null) {
// write map to database
System.out.println(map);
}
}
}
CheckQueue queueChecker = new CheckQueue ();
Future<?> future = executor.submit(queueChecker);
// this interrupts the database thread, which sends it into its catch block
// where it processes the rest of the queue and exits
queueChecker.cancel();
类CheckQueue实现可运行{
私有易失性布尔值=false;
public void cancel(){cancelled=true;}
公开募捐{
地图;
试一试{
而(!取消){
//阻塞,直到队列中有可用的映射,或直到中断
map=queue.take();
如果(取消)休息;
//将映射写入数据库
系统输出打印项次(map);
}捕捉(中断异常e){
}
而((map=queue.poll())!=null){
//将映射写入数据库
系统输出打印项次(map);
}
}
}
CheckQueue queueChecker=新的CheckQueue();
Future=executor.submit(队列检查器);
//这会中断数据库线程,数据库线程将其发送到catch块中
//它处理队列的其余部分并退出
queueChecker.cancel();
您粘贴的代码片段几乎没有问题,如果您修复了这些问题,应该可以正常工作。
1.您正在使用无限循环从阻塞队列中获取元素,并试图使用future来打破这种情况。这绝对不是一种好方法。这种方法的问题是,您的数据库线程可能永远不会运行,因为它可能会被调用线程中运行的未来任务取消,甚至在它运行之前。这容易出错。
-您应该固定次数地运行while循环(您已经知道有多少生产者,或者您将获得多少次响应)
此外,提交给executor服务的任务应该是独立的任务…此处,您的数据库任务依赖于其他任务的执行..如果您的执行策略发生更改,这也可能导致死锁..例如,如果您使用单线程池executor,并且如果已计划数据库线程,它将阻止等待生产者添加队列中的数据
- 一个好的方法是在同一线程中创建检索数据和更新数据库的任务
- 或者先检索所有响应,然后并行执行数据库操作
公共无效写入事件(最终地图数据){
final executor服务executor=Executors.newFixedThreadPool(3);
@抑制警告(“未选中”)
最终映射输出=(Map)data.get(modelstants.EVENT_HOLDER);
对于(最终ModuleRegistration.ModuleHolderEntry:ModuleRegistration.getInstance()){
执行者提交(新的可运行(){
公开募捐{
试一试{
最终映射响应=entry.getPlugin().process(输出);
//处理响应并更新数据库。
系统输出打印项次(map);
}捕获(可丢弃的e){
//句柄执行
}最后{
//清理资源
}
}
});
}
//这将等待正在运行的线程完成。这是一个有序的关闭。
executor.shutdown();
}
我不是这些方面的专家,所以我不得不查阅很多资料。但我担心将来。cancel
可能会中断一些重要的操作(甚至可能中断阻塞队列
应该是原子的操作)。您是否尝试过其他同步方法?例如,将volatile boolean添加到匿名Runnable,添加一个方法来设置它,在设置boolean时让您的循环处于Runnable出口,并让其他类使用“set”方法而不是future.cancel
。这样你会有更多的控制权。但我只是猜测。按照我的建议,你可能需要编写Runnable
的命名子类,并声明该类的一个变量,以便调用“set my cancel flag”方法。我对这种方法感到困惑,因为我不确定如何将其与我的cpde集成。我无法使其工作。@TrekkieTechieT-T:我在编辑中修复了一些错误。(我的取消
声明搞砸了,即使不再依赖中断,您仍然必须捕获中断异常
)如果你已经让它编译了,但结果相同,那就意味着我的猜测是错误的。如果你让它编译了,但它让事情变得更糟,那么我需要知道新的不良行为是什么。感谢Amol的建议。你的一些解释对我来说是有意义的。有没有办法,你可以在我的基础上给我举个例子
class CheckQueue implements Runnable {
private volatile boolean cancelled = false;
public void cancel() { cancelled = true; }
public void run() {
Map<String, String> map;
try {
while(!cancelled) {
// blocks until a map is available in the queue, or until interrupted
map = queue.take();
if (cancelled) break;
// write map to database
System.out.println(map);
} catch (InterruptedException e) {
}
while((map = queue.poll()) != null) {
// write map to database
System.out.println(map);
}
}
}
CheckQueue queueChecker = new CheckQueue ();
Future<?> future = executor.submit(queueChecker);
// this interrupts the database thread, which sends it into its catch block
// where it processes the rest of the queue and exits
queueChecker.cancel();
final ExecutorService executor = Executors.newFixedThreadPool(3);
@SuppressWarnings("unchecked")
final Map<String, String> outputs = (Map<String, String>)data.get(ModelConstants.EVENT_HOLDER);
for (final ModuleRegistration.ModulesHolderEntry entry : ModuleRegistration.getInstance()) {
executor.submit(new Runnable () {
public void run() {
try {
final Map<String, String> response = entry.getPlugin().process(outputs);
//process the response and update database.
System.out.println(map);
} catch (Throwable e) {
//handle execption
} finally {
//clean up resources
}
}
});
}