没有从提交到线程池的作业获得任何输出

时间:2012-05-01 14:38:41

标签: java multithreading static

假设我有A类和B类.A类只有一个主方法,代码如下:

public class A{
    public static void main(String[] args){
        String xput = "";
        ExecutorService pool = Executors.newFixedThreadPool(4);
        for(int i = 1; i < number; i++){
            pool.submit(new B(list.get(i-1)));
            xput = B.returnValue;
            System.out.println(xput);//testing purposes
        }
    }
}

B类扩展了Thread,看起来像这样:

public class B extends Thread{

    static String returnValue = "";        

    public B(String x){
        super(x);
    }

    public void run(){
        double x = 20;
        returnValue += "Grand total: " +
            NumberFormat.getCurrencyInstance().format(x) + "\n";
    }
}

然而System.out.println(xput)除了空行外不会打印任何内容。谁知道为什么?我的类有比这更多的代码,但由于我没有得到任何输出,我从一个小案例开始。

2 个答案:

答案 0 :(得分:4)

此代码受到许多竞争条件的影响,因为它们都在更新相同的static String returnValue。当调用System.out.println(xput)时,线程实际上可能还没有运行。您需要使用future.get()方法等待每个线程完成,并且您不能在将它们提交给线程池的同一循环中执行此操作。

由于4个线程将同时运行,并且它们都在更新相同的static字段,因此您需要围绕该变量提供一些同步。我建议的是使用Future的{​​{1}}功能而不是修改静态字段。以下内容应该有效:

ExecutorService

List<Future<String>> futures = new ArrayList<Future<String>>(); for(int i = 1; i < number; i++){ B b = new B(list.get(i - 1)); // submit the job b add the resulting Future to the list futures.add(pool.submit(b)); } // all of the jobs are submitted now StringBuilder sb = new StringBuilder(); for (Future<String> future : futures) { // now join with each of the jobs in turn and get their return value sb.append(future.get()); } System.out.println(sb.toString()); // you should implement Callable _not_ extend thread public class B implements Callable<String> { public String call(){ ... return "some string"; } } 的{​​{1}}功能允许您从线程池处理的每个作业中获取结果。您可以Future ExecutorService个类,它们可以从submit()方法返回结果Callable(或其他对象)。

此外,您的String应该实施call()而不是B。虽然它会起作用,但这只是因为Callable也实现了Thread。线程池有自己的内部线程,您只需向其提交ThreadRunnable个对象。

最后,在处理列表(或任何Java集合)时,不应使用Runnable循环,而应养成使用的习惯:

Callable

如果您 使用for (int i,那么至少从0到列表的 for(String x : list) { B b = new B(x); ...

for (int i

这样,如果你改变列表的大小,你也不必记得改变你的循环。

答案 1 :(得分:0)

没有打印任何内容,因为您在设置之前检查了'returnValue'。将'returnValue'设为静态也意味着所有线程都将写入相同的共享变量。

如果要为线程设置返回值,请让它们实现callable<T>而不是线程,并将它们传递给<T> Future<T> submit(Callable<T> task)方法。在为您要查找的值返回的get()上调用Future<T>

相关问题