【问题标题】:Execute multiple threads each one for a certain amount of time in java在java中每个线程执行一定时间
【发布时间】:2015-01-29 15:40:38
【问题描述】:

我正在将文件发送到创建文件的本地服务器。我的问题发生在用户一个接一个地执行多项操作时,如果其中一个请求在 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 分钟的情况

【问题讨论】:

    标签: java multithreading timer executor


    【解决方案1】:

    看看 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 可以让您控制线程数、线程池已满时使用的队列大小以及其他不错的功能。
    【解决方案2】:

    您可以手动执行此操作,但使用 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 中正确处理异常块。
    • 问题是我不想等待 5,它应该在最多 1 分钟内到达,但如果 5 分钟并且什么都没有,那么这是一个错误,或者如果我执行 future.get(),无论如何都会等待 5 分钟
    • > 如果我执行 future.get(),无论如何它都会等待 5 分钟。这是不正确的。 Future.get(5, TimeUnit.MINUTES) 实际上按照您想要的方式工作。它一直等到响应返回,如果 5 分钟后没有响应,则返回 TimeoutException 失败。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2021-10-12
      • 1970-01-01
      • 2017-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多