繁体   English   中英

线程安全问题,同时使每个捆绑包的线程超时

[英]Thread safety issue while timing out the thread for each bundle

我正在一个项目中,我将具有不同的包/模型。 让我们举个例子,假设我有4个捆绑包,每个捆绑包都有一个方法名process

以下是我应该做的事情-

  1. 我需要使用多线程并行调用所有这4个Bundles process method ,并且每个bundle中的process method将返回一个映射,然后将该映射写入同一线程中或执行最佳方法的数据库中(我不确定在这是正确的方法)。
  2. 我也想在线程级别启用某种超时功能。 这意味着如果某个Bundle需要花费很多时间来执行,那么Bundle线程应该超时并记录一个错误,指出该特定的bundle超时了,因为花费了很多时间。

我所做的以下尝试很可能是有缺陷的,错误处理绝不是完整的。 有人可以指导我在错误处理案例中应该做什么吗?

下面是我的方法,它将以多线程方式调用所有捆绑包的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM