简体   繁体   English

Java并发:奇怪的输出

[英]Java concurrency: weird output

I'm fooling around with Java threads and I wrote this little program that creates several threads and runs them. 我在鬼混Java线程,并编写了这个小程序来创建多个线程并运行它们。 In each thread a value is incremented multiple times. 在每个线程中,值会多次增加。 I used ThreadLocal class so that there's no contention for resources. 我使用ThreadLocal类,这样就不会争用资源。

Source: 资源:

class MyValueHolder {

    public static ThreadLocal<Integer> value = new ThreadLocal<Integer>()
    {
        protected Integer initialValue() {
            return 0;
        }
    };

    public static void increment() {
        value.set(value.get() + 1);
    }

    public static Integer get() {
        return value.get();
    }
}

class MyTask implements Runnable {

    public static int counter;

    public MyTask() {
        counter++;
    }

    public void run() {

        for(int i = 0; i < 100; i++) {
            MyValueHolder.increment();
        }
        System.out.println("MyTask " + counter + ", Value " + MyValueHolder.get());
    }
}

public class Main {

    public static void main(String[] args) {

        ExecutorService es = Executors.newCachedThreadPool();

        for(int i = 0; i < 5; i++) {

            es.execute(new MyTask());
        }

        es.shutdownNow();
    }
}

After completion the output is most of the time this: 完成后,大部分时间输出如下:

MyTask 5, Value 100
MyTask 5, Value 100
MyTask 5, Value 100
MyTask 5, Value 100
MyTask 5, Value 100

Which is what I'd expect to see. 这是我期望看到的。

However, sometimes I get something like this: 但是,有时我会得到如下信息:

MyTask 2, Value 100
MyTask 4, Value 200
MyTask 5, Value 300
MyTask 5, Value 100
MyTask 5, Value 100

Now this is confusing. 现在,这令人困惑。 Why do the values differ even though each task does absolutely the same thing? 为什么即使每个任务做的完全相同,值也不同?

The CachedThreadPoolExecutor reuses threads if a Runnable finishes before you have added all Runnable s. 如果在添加所有Runnable之前Runnable完成,则CachedThreadPoolExecutor将重用线程。 If this happens the ThreadLocal of that thread will also be reused. 如果发生这种情况,该线程的ThreadLocal也将被重用。

Like stated above, ThreadLocal is being reused. 如上所述,ThreadLocal被重用。

For counter, use AtomicInteger instead and set an initial value. 对于计数器,请改用AtomicInteger并设置一个初始值。 counter++ is not an atomic operation, its two operations and is not thread safe. counter ++不是原子操作,它不是两个操作,也不是线程安全的。

threads will keep running while you get an output you should wait for them to finish you can try isAlive(); 当您获得输出时,线程将继续运行,您应该等待它们完成,然后可以尝试isAlive();。 with the threads 与线程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM