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
                }               
            }
        });
    }