首先,我必须说,我很新的API的java.util.concurrent,所以也许我做的是完全错误的。

什么我想要做什么?

我有基本上运行2个独立的处理的Java应用程序(称为 myFirstProcess mySecondProcess ),但这些处理,必须在同一时间运行。

所以,我想这样做:

public void startMyApplication() {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
    FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
    executor.execute(futureOne);
    executor.execute(futureTwo);
    while (!(futureOne.isDone() && futureTwo.isDone())) {
        try {
            // I wait until both processes are finished.
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    logger.info("Processing finished");
    executor.shutdown();
    // Do some processing on results
    ...
}

myFirstProcess mySecondProcess 是实现Callable<Object>类,并且其中所有的处理是在呼叫()方法进行说明。

这是合作得非常好,但我不知道它是做正确的方式。 是做我想做什么好办法?如果没有,你可以给我一些提示,以提高我的代码(现在仍然保持尽可能简单)。

有帮助吗?

解决方案

您会更好使用get()方法。

futureOne.get();
futureTwo.get();

这两者等待来自线程,它完成处理的通知,这可以节省的忙等待与 - 计时器您现在使用效率不高也不优雅。

作为奖励,你有API get(long timeout, TimeUnit unit)它允许你定义一个最大时间的线程休眠和等待响应,否则继续运行。

请参阅更多信息的Java API

其他提示

以上FutureTask的用途是容许的,但绝对不惯用。你实际上是一个包装的额外的的在你身边提交FutureTask的一个ExecutorService。你FutureTask被视为由Runnable一个ExecutorService。在内部,它包你FutureTask-AS-Runnable在新FutureTask并返回给你作为一个Future<?>

相反,你应该提交您的Callable<Object>实例到的 CompletionService 。你可以通过Callable顺路2个submit(Callable<V>)s,然后转身和呼叫CompletionService#take()两次(一次为每个提交Callable)。这些调用将阻塞,直到一个,然后其他提交的任务已经完成。

既然你已经在手的Executor,构建一个新的周围ExecutorCompletionService ,并在那里放下你的任务。不要旋转和睡眠等待; CompletionService#take()将阻塞,直到任一的你的任务之一是完全的(无论是完成运行或取消)或线程等待take()被中断。

尤瓦的解决方案是细。作为替代方案也可以做到这一点:

ExecutorService executor = Executors.newFixedThreadPool();
FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
executor.execute(futureOne);
executor.execute(futureTwo);
executor.shutdown();
try {
  executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  // interrupted
}

什么是这种方法的优势在哪里?这里没有很大的差异真的只是这样,你停止执行接受任何更多的任务(你可以做到这一点的其他方式)。我倾向于选择这个成语一个虽然。

此外,如果要么得到()抛出一个异常,你可以在你的代码的一部分,它假定这两个任务都做了,这可能是坏的结束。

可以使用的invokeAll(集合....)方法

package concurrent.threadPool;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class InvokeAll {

    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(5);
        List<Future<java.lang.String>> futureList = service.invokeAll(Arrays.asList(new Task1<String>(),new Task2<String>()));

        System.out.println(futureList.get(1).get());
        System.out.println(futureList.get(0).get());
    }

    private static class Task1<String> implements Callable<String>{

        @Override
        public String call() throws Exception {
            Thread.sleep(1000 * 10);
            return (String) "1000 * 5";
        }

    }

    private static class Task2<String> implements Callable<String>{

        @Override
        public String call() throws Exception {
            Thread.sleep(1000 * 2);
            int i=3;
            if(i==3)
                throw new RuntimeException("Its Wrong");
            return (String) "1000 * 2";
        }

    }
}

您可能需要使用的CyclicBarrier 如果你有兴趣在同一时间开始的线程,或者等待他们完成,然后做一些进一步的处理。 看到的Javadoc获得更多信息。

如果您futureTasks是超过2,请考虑[ListenableFuture][1]

  

当的若干操作应尽快开始作为另一操作   开始 - “扇出” - ListenableFuture只是工作:它触发所有的   所请求的回调。具有稍微更多的工作,我们可以通过“的扇入下,”或   触发ListenableFuture得到尽快计算出其他几个   期货已经全部完成。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top