在Java中执行多个线程,每个线程运行一定时间

3

我正在向本地服务器发送文件,该服务器会返回一个文件。我的问题是当用户连续执行多个操作时,如果其中一个请求在5分钟内没有收到反馈文件,我需要显示错误消息。

我该如何处理所有这些请求?我使用了newSingleThreadScheduledExecutor每隔一分钟检查反馈文件是否存在,但我不知道如何处理多个请求并为每个请求保持倒计时,以便在5分钟的情况下对其进行处理。 我的尝试:

ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(listPrinter.size()));
        for(int i=0;i<list.size();i++){
            try {

                final File retrievedFile = new File("/home/"+list.get(i)+".csv");

                ListenableFuture<File> future = executor.submit(new Callable<File>() {
                    public File call() {
                        // Actually send the file to your local server
                        // and retrieve a file back

                        if(retrievedFile.exists())
                        {
                            new Notification("file exits").show(Page.getCurrent());
                        }
                        else{
                            new Notification("file no exits").show(Page.getCurrent());
                        }
                        return retrievedFile;
                    }
                });
                future.get(5, TimeUnit.MINUTES);
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            } catch (ExecutionException ex) {
                Exceptions.printStackTrace(ex);
            } catch (TimeoutException ex) {
                Exceptions.printStackTrace(ex);
                new Notification("Time out").show(Page.getCurrent());
            }
        }

但是它只会在开头执行一次,之后添加文件时不会再有任何反应。

使用watchService能否实现这个功能?对我来说这个方法非常有效,但我不知道5分钟的情况。

3个回答

2

请看一下Future接口的未来界面:

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html

这应该非常适合您的问题。

当您运行一个线程时,结果可能是一个Future,它是异步任务的结果,并且您可以针对每个正在启动的异步任务拥有一个Future。

Future<File> sendReceiveFile(File inputFile) {
    final Future<File> future = new YourFuture<File>(...);
    new Thread() {
        @Override
        public void run() {
            File outputFile = null;
            try {
                 outputFile = SendFileToServer(inputFile);
            } catch (final Exception e) {
                // do something
            } finally {
                future.setValue(fileOutput);
            }
        }
    }.start();
    return future;
}

在你的主要代码中:

Future<File> future = sendReceiveFile(myFile);
File outputFile = null;
try {
    outputFile = future.get(1, TimeUnit.MINUTE);
} catch(TimeOutException e) {
    // do something
}

使用 new Thread() { }.start() 不是非常健壮。ThreadPoolExecutor 可以让您控制线程数,当线程池已满时要使用的队列大小,以及其他一些不错的功能。 - fps

0

你可以手动完成这个任务,但使用Guava ListenableFuture会更好:

// Here we create a fixed thread pool with 10 threads and an inifinite-capacity queue
ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

final File fileToSend = ...; // 

ListenableFuture<File> future = executor.submit(new Callable<File>() {
    public File call() {
        // Actually send the file to your local server
        // and retrieve a file back
        File retrievedFile = YourLocalServer.sendAndRetrieve(fileToSend);
        return retrievedFile;
    }
});

Futures.addCallback(future, new FutureCallback<File>() {

    public void onSuccess(File retrievedFile) {
        // Handle the successfully retrieved file when it returns
    }

    public void onFailure(Throwable thrown) {
        // Handle the error
    }
});

通过异步发送文件,您可以在任何时候发送和检索多个文件。然后,当服务器响应(无论是检索到的文件还是错误)时,您可以在其返回时处理响应(检索到的文件或异常),而无需等待它。这意味着当本地服务器有可用响应时,onSuccess()onFailure() 方法将自动执行。

看起来不错,但问题不在于启动多个线程,而在于对于每个请求都保持5分钟倒计时的情况! - user2137817
如果您想等待每个请求到本地服务器的时间为5分钟,请使用future.get(timeout, unit)而不是Futures.addCallback(),并在try/catch块中正确处理异常。 - fps
事情是我不想等5分钟,它应该在1分钟内出现,但如果超过5分钟仍未出现,则会出现错误;或者如果我使用future.get(),无论如何它都会等待5分钟。 - user2137817
如果我执行future.get(),它将无论如何等待5分钟。这是不正确的。实际上,Future.get(5, TimeUnit.MINUTES)可以按照您想要的方式工作。它会等待响应返回,或者在5分钟后如果没有响应则失败并抛出TimeoutException异常。 - fps

0

我通过使用一个Timer解决了这个问题,它每隔5分钟执行一次,获取过去5分钟内发生的所有db事务并且没有得到任何响应的事务,并显示我的错误代码。它运行得非常好。感谢大家的帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接