我是否以正确的方式使用可调用和期货多线程(java)?

时间:2011-06-21 18:27:55

标签: java multithreading

我需要完成一些多线程的任务 我事先知道,当所有任务完成后,我将继续我的计划 以下代码是否适用于此目的?

  public void test() {
    Callable<String> myCall = new Callable() {

        @Override
        public String call() throws Exception {
            return doDomething();
        }
    };


    Callable<String> myCall2 = new Callable() {

        @Override
        public String call() throws Exception {
            return doDomething2();
        }
    };

    ExecutorService executor = Executors.newFixedThreadPool(2);
    List<Callable<String>> list = Arrays.asList(myCall,myCall2);
    List<Future<String>> futuresList = executor.invokeAll(list);

    String result1 = futuresList.get(0).get();

    String result2 = futuresList.get(0).get();

    //...
}

我正在尝试将其更改为使用泛型:

public void test() {
Callable<?> myCall = new Callable() {

    @Override
    public String call() throws Exception {
        return doDomething();
    }
};


Callable<?> myCall2 = new Callable() {

    @Override
    public String call() throws Exception {
        return doDomething2();
    }
};

ExecutorService executor = Executors.newFixedThreadPool(2);
List<Callable<?>> list = Arrays.asList(myCall,myCall2);
List<Future<?>> futuresList = executor.invokeAll((Collection<? extends Callable<?>>)list);

String result1 = futuresList.get(0).get();

String result2 = futuresList.get(0).get();

// ...
}

我收到以下编译错误:

  

ExecutorService类型中的方法invokeAll(Collection<? extends Callable<T>>)不适用于参数(Collection<capture#2-of ? extends Callable<?>>)

2 个答案:

答案 0 :(得分:2)

除了你两次访问第0个索引之外,我没有看到任何错误。

此编辑是关于如何在没有ExecutorService的情况下实现它的问题。正如ColinD所说,你真的不应该我会说明原因

要获得相同的功能集,您需要两个对象并使用两个线程作为锁存器

String result1 = null;

String result2 = null;

public void test() {
    Thread thread1 = new Thread(new Runnable(){
        public void run(){
            result1 = doSomething();
        }
    });
    Thread thread2 = new Thread(new Runnable(){
        public void run(){
            result2 = doSomething2();
        }
    });
    thread1.start(); 
    thread2.start();
    thread1.join(); 
    thread2.join();
    ...
    ...

}

现在如果你想添加另一个线程/工作单元,那么你需要

Thread thread3 = new Thread(new Runnable(){
            public void run(){
                result3 = doSomething3();
            }
        });
thread3.start();
thread3.join();

等等。因此,您的解决方案是更好的方法。

答案 1 :(得分:1)

那么,让我成为魔鬼的拥护者吧。 在这个例子中,实际上可以直接回击你的唯一事情就是你正在同步调用两个方法,这对其他程序员来说可能并不那么明显。

我想这只是一个例子,但其他程序员可能不会认识到doSomethingdoSomething2不应该具有'共享可变状态',因为它们是同步执行的。在这个设置中并不是那么明显。

所以我建议将逻辑放在单独的类中。