简体   繁体   中英

Java Thread Count doesn't work

Why is count 0?

I start the thread 1 then I start thread 2. Count should be 2000. But it shows count to be 0. Someone please explain in simple terms.

public class App {
    private int count = 0;

    public static void main(String[] args) {
        App app = new App();
        app.doWork();
    }

    public void doWork(){
        Thread t1 = new Thread(new Runnable(){
            public void run(){
                for(int i = 0;i < 10000;i++){
                    count++;
                }
            }
        });

        Thread t2 = new Thread(new Runnable(){
            public void run(){
                for(int i = 0;i < 10000;i++){
                    count++;
                }
            }
        });
        t1.start();
        t2.start();

        System.out.println("Count is: " + count);
    }
}

At the time you're printing out your thread count, the threads have not finished executing yet.

To demonstrate, add a Thread.sleep() instruction before printing out the thread count:

public class App {
    private int count = 0;

    public static void main(String[] args) throws InterruptedException {
        App app = new App();
        app.doWork();
    }

    public void doWork() throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    count++;
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    count++;
                }
            }
        });

        t1.start();
        t2.start();

        Thread.sleep(5000);

        System.out.println("Count is: " + count); // Count is: 20000
    }
}

Also note that operations on primitives are not thread-safe and that the count++ operation is not atomic . You should synchronize access to your count variable, or use an AtomicInteger or LongAdder instead of an int . As it stands, you might end up with a count anywhere between zero and 20,000.

Integer's increment is not safe to multithreading. You should use AtmoicInteger like this:

public class App {

    private AtomicInteger count = new AtomicInteger(0);

    public static void main(String[] args) throws InterruptedException {
        App app = new App();
        app.doWork();
    }

    public void doWork() throws InterruptedException {
        Thread t1 = new Thread(new Runnable(){
            public void run(){
                for(int i = 0;i < 10000;i++){
                    count.getAndIncrement();
                }
            }
        });

        Thread t2 = new Thread(new Runnable(){
            public void run(){
                for(int i = 0;i < 10000;i++){
                    count.getAndIncrement();
                }
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Count is: " + count);
    }
}

It is because you are printing count in main thread. Main thread executed in its normal way , before child thread started. That's why your count is 0 , try to print count after a while , like put Thread.sleep(2000) before printing it.

You need to make the code block which increments the count as synchronized in order to avoid the race condition .

In addition to this there are multiple ways to solve this problem-
1. Hard code Thread.sleep(miliseconds value) in Main thread. [Not recommended]
2. join() the two threads to the main Thread so that the control returns to the main thread only when the execution of the two threads is complete.

public class App implements Runnable {
    private int count = 0;

    public static void main(String[] args) throws InterruptedException {
        App app = new App();
        app.doWork();
    }

    public void doWork() throws InterruptedException {
        Thread t1 = new Thread(this, "Thread - 1");
        Thread t2 = new Thread(this, "Thread - 2");

        t1.start();
        t2.start();

        //1.
        t1.join();
        t2.join();

        //2.
        //Thread.sleep(1000);

        System.out.println("Count is: " + count); // Count is: 2000
    }

    @Override
    public synchronized void run() {

        for (int i = 0; i < 1000; i++) {
            count++;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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