使用错误管理在Java中运行多个线程

时间:2016-01-21 09:45:38

标签: java multithreading

我有一个像IJob这样的工作界面:

public interface IJob {
    public void execute();
}

在我的应用程序中,我有多个实现此接口的类,如IJob1和IJob2:

public class IJob1 implements IJob{
@Override
public void execute(){
    System.out.println("IJob1\n");
    }
}

public class IJob2 implements IJob{
@Override
public void execute(){
    System.out.println("IJob2\n");
    }
}

由于要运行的作业数量稳步增加,我想创建一个新作业,它接受一个I​​Job实例列表并并行运行它们。新实现用于并行运行作业的线程数量应该是可配置的。如果其中一个作业抛出异常,那么所有其他当前正在运行的作业也应该停止,而execute()方法应该将异常传递给调用者。

我写了这个,但我无法运行工作并检查是否有错误:

import java.util.LinkedList;

public class WorkQueue
{
    private final int nThreads;
    private final IJob[] threads;
    private final LinkedList queue;

    public WorkQueue(int nThreads)
    {
        this.nThreads = nThreads;
        queue = new LinkedList();
        threads = new IJob[nThreads];

        for (int i=0; i<nThreads; i++) {
            threads[i] = new IJob();
            threads[i].execute();
        }
    }

    public void execute(Runnable r) {
    synchronized(queue) {
        queue.addLast(r);
        queue.notify();
    }
}

private class PoolWorker extends Thread {
    public void run() {
        Runnable r;

        while (true) {
            synchronized(queue) {
                while (queue.isEmpty()) {
                    try
                    {
                        queue.wait();
                    }
                    catch (InterruptedException ignored)
                    {
                    }
                }

                r = (Runnable) queue.removeFirst();
            }

            // If we don't catch RuntimeException, 
            // the pool could leak threads
            try {
                r.run();
            }
            catch (RuntimeException e) {
                // You might want to log something here
            }
        }
    }
}
}

请你帮我一些帮助吗? 非常感谢你。

2 个答案:

答案 0 :(得分:5)

我建议使用托管线程池。典型的模式是使用Java Executors来获取ExecutorService。 ExecutorService通常使用线程池和作业队列来实现。在ExecutorService上,有一些方法,如shutdownNow(),&#34;尝试停止所有正在执行的任务&#34;。这听起来像你想要做的。

实施例,

List<Callable<Result>> tasks = new ArrayList<>();
for (final Object job: jobs) {
    final Callable<Result> task = new Callable<Result>() {
            @Override
            public Result call() throws Exception {
                // Do job here
                return result;
            }
        };
    tasks.add(task);
}
final numOfThreads = 20; 
final ExecutorService executor = Executors.newFixedThreadPool(numOfThreads);
try {
    executor.invokeAll(tasks);
} finally {
    executor.shutdownNow();
}

答案 1 :(得分:4)

  

我想创建一个新作业,它接受一个I​​Job实例列表并并行运行它们。新实现用于并行运行作业的线程数量应该是可配置的。如果其中一个作业抛出异常,那么所有其他当前正在运行的作业也应该停止,而execute()方法应该将异常传递给调用者。

这是使用parallelStream()将使您的生活更简单的地方。你可以做到

list.parallelStream().
    .forEach(IJob::execute);

您可能会发现根本不需要框架,您可以将此代码合并到调用者中。 e.g。

Map<String, T> map = dataSet.parallelStream()
                            .map(t -> t.transform1())
                            .filter(t -> t.isGood())
                            .collect(Collectors.groupingByConcurrent(t.getKey()));