Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 创建自中断服务_Java_Multithreading_Executorservice_Runnable_Interrupted Exception - Fatal编程技术网

Java 创建自中断服务

Java 创建自中断服务,java,multithreading,executorservice,runnable,interrupted-exception,Java,Multithreading,Executorservice,Runnable,Interrupted Exception,我有一个任务要处理一个文件目录,如果出现任何问题,需要抛出一个IOException。我还需要它运行得更快,所以我将完成的工作拆分为多个线程,并等待它们的终止。它看起来像这样: //Needs to throw IOException so the rest of the framework handles it properly. public void process(File directory) throws IOException { ExecutorService execu

我有一个任务要处理一个文件目录,如果出现任何问题,需要抛出一个IOException。我还需要它运行得更快,所以我将完成的工作拆分为多个线程,并等待它们的终止。它看起来像这样:

//Needs to throw IOException so the rest of the framework handles it properly.
public void process(File directory) throws IOException {
    ExecutorService executorService =
        new ThreadPoolExecutor(16, 16, Long.MAX_VALUE, TimeUnit.NANOSECONDS,
            new LinkedBlockingQueue<Runnable>());

    //Convenience class to walk over relevant file types.
    Source source = new SourceImpl(directory);
    while (source.hasNext()) {
        File file = source.next();
        executorService.execute(new Worker(file));
    }

    try {
        executorService.shutdown();
        executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    } catch (InterruptedException e) {
        executorService.shutdownNow();
        throw new IOException("Worker thread had a problem!");
    }
}
所需的行为是,如果任何工作线程具有IOException,那么生成线程就会知道它,并反过来抛出自己的IOException。这是我能想到的允许工作线程发出错误信号的最佳方式,但我仍然不确定我是否正确设置了它

那么,首先,这能满足我的期望吗?如果工作线程在run()中有错误,将调用
thread.currentThread().interrupt()导致抛出InterruptedException,使其被阻塞
executorService.awaitTermination捕获(Long.MAX_值,时间单位为纳秒)

其次,如果一个正在运行的工作线程在所有线程排队之前调用其中断,将会发生什么情况;在阻塞try/catch阻塞之前

最后(也是最重要的),有没有更优雅的方式来实现我的目标?我想让所有无数的子线程都执行,直到完成或其中任何一个出现错误为止,此时我希望在生成线程中处理它(通过有效地使整个目录失败)


解决方案

根据答案,下面是我最终使用的实现。它很好地处理了我的异步需求,并在IOException上以干净和相对较快的速度失败

public void process(File directory) throws IOException {
    //Set up a thread pool of 16 to do work.
    ExecutorService executorService = Executors.newFixedThreadPool(16);
    //Arbitrary file source.
    Source source = new SourceImpl(directory);
    //List to hold references to all worker threads.
    ArrayList<Callable<IOException>> filesToWork =
        new ArrayList<Callable<IOException>>();
    //Service to manage the running of the threads.
    ExecutorCompletionService<IOException> ecs =
        new ExecutorCompletionService<IOException>(executorService);

    //Queue up all of the file worker threads.
    while (source.hasNext())
        filesToWork.add(new Worker(file));

    //Store the potential results of each worker thread.
    int n = filesToWork.size();
    ArrayList<Future<IOException>> futures =
        new ArrayList<Future<IOException>>(n);

    //Prepare to return an arbitrary worker's exception.
    IOException exception = null;
    try {
        //Add all workers to the ECS and Future collection.
        for (Callable<IOException> callable : filesToWork)
            futures.add(ecs.submit(callable));
        for (int i = 0; i < n; i++) {
            try {
                //Get each result as it's available, sometimes blocking.
                IOException e = ecs.take().get();
                //Stop if an exception is returned.
                if (e != null) {
                    exception = e;
                    break;
                }
            //Also catch our own exceptions.
            } catch (InterruptedException e) {
                exception = new IOException(e);
                break;
            } catch (ExecutionException e) {
                exception = new IOException(e);
                break;
            }
        }
    } finally {
        //Stop any pending tasks if we broke early.
        for (Future<IOException> f : futures)
            f.cancel(true);
        //And kill all of the threads.
        executorService.shutdownNow();
    }

    //If anything went wrong, it was preserved. Throw it now.
    if (exception != null)
        throw exception;
}
public void进程(文件目录)引发IOException{
//设置16个线程池来执行工作。
ExecutorService ExecutorService=Executors.newFixedThreadPool(16);
//任意文件源。
Source Source=新的SourceImpl(目录);
//保存对所有工作线程的引用的列表。
ArrayList文件工作=
新的ArrayList();
//服务来管理线程的运行。
ExecutorCompletionService ecs=
新的ExecutorCompletionService(executorService);
//将所有文件工作线程排队。
while(source.hasNext())
添加(新工作者(文件));
//存储每个辅助线程的潜在结果。
int n=filesToWork.size();
ArrayList期货=
新ArrayList(n);
//准备返回任意工作进程的异常。
IOException=null;
试一试{
//将所有工人添加到ECS和未来集合。
for(可调用可调用:filesToWork)
期货.add(ecs.submit(callable));
对于(int i=0;i

//正常工作,并在出错时返回(而不是抛出)IOException对象。
私有类工作程序实现了可调用{
私人最终文件;
公共工作者(文件){this.File=File;}
@凌驾
公共IOException调用(){
试一试{
//工作
}捕获(IOE异常){
返回e;
}
返回null;
}
}

一如既往,线程之间的最佳通信是队列。让每个工作线程发送一条消息,描述其执行是如何完成的,并让生成线程从队列中读取。此外,由于生成线程知道它生成了多少个工作线程,因此它可以只计算消息以知道所有工作线程何时完成,而不依赖于池关闭。

这样调用
中断()
不会影响主线程


您应该做的是将您的工作人员设置为可调用的,而不是可运行的,并允许故障异常离开调用()方法。然后,使用命令执行所有工作人员。这将允许您确定每个任务的状态,并在其中一个任务失败时在主线程中采取操作。

使执行
的工作人员可调用
,您可以执行以下操作:

public void process(File directory) throws IOException {
    ExecutorService executorService = new ThreadPoolExecutor(16, 16,
            Long.MAX_VALUE, TimeUnit.NANOSECONDS,
            new LinkedBlockingQueue<Runnable>());

    // Convenience class to walk over relevant file types.
    List<Future<Void>> futures = new ArrayList<Future<Void>>();
    Source source = new SourceImpl(directory);
    while (source.hasNext()) {
        File file = source.next();
        futures.add(executorService.submit(new Worker(file)));
    }

    try {
        for (Future<Void> future : futures) {
            future.get();
        }
    } catch (ExecutionException e) {
        throw new IOException("Worker thread had a problem!", e.getCause());
    } catch (InterruptedException e) {
        throw new IOException("Worker thread had a problem!", e);
    } finally {
        executorService.shutdown();
    }
}
public void进程(文件目录)引发IOException{
ExecutorService ExecutorService=新线程池Executor(16,16,
Long.MAX_值,时间单位为纳秒,
新建LinkedBlockingQueue());
//方便类浏览相关文件类型。
列表期货=新的ArrayList();
Source Source=新的SourceImpl(目录);
while(source.hasNext()){
File=source.next();
futures.add(executorService.submit(新员工(文件));
}
试一试{
for(未来:未来){
future.get();
}
}捕获(执行例外){
抛出新IOException(“工作线程有问题!”,e.getCause();
}捕捉(中断异常e){
抛出新IOException(“工作线程有问题!”,e);
}最后{
executorService.shutdown();
}
}

Thread.currentThread().interrupt();仅中断当前正在运行的线程,在本例中,该线程就是工作线程本身。所有其他正在运行的线程都不受此中断的影响。并且您不能依赖InterruptedException,因为它可能会被抛出,也可能不会被抛出。和e
//Does work, and returns (not throws) an IOException object on error.
private class Worker implements Callable<IOException> {
    private final File file;
    public Worker(File file) { this.file = file; }

    @Override
    public IOException call() {
        try {
            //Do work
        } catch (IOException e) {
            return e;
        }
        return null;
    }
}
public void process(File directory) throws IOException {
    ExecutorService executorService = new ThreadPoolExecutor(16, 16,
            Long.MAX_VALUE, TimeUnit.NANOSECONDS,
            new LinkedBlockingQueue<Runnable>());

    // Convenience class to walk over relevant file types.
    List<Future<Void>> futures = new ArrayList<Future<Void>>();
    Source source = new SourceImpl(directory);
    while (source.hasNext()) {
        File file = source.next();
        futures.add(executorService.submit(new Worker(file)));
    }

    try {
        for (Future<Void> future : futures) {
            future.get();
        }
    } catch (ExecutionException e) {
        throw new IOException("Worker thread had a problem!", e.getCause());
    } catch (InterruptedException e) {
        throw new IOException("Worker thread had a problem!", e);
    } finally {
        executorService.shutdown();
    }
}