Java 易失性原子整数不工作

Java 易失性原子整数不工作,java,multithreading,Java,Multithreading,嗨,我在试。我从主线程创建10个线程,并打印每个线程的静态计数器值 产量不确定。有人能告诉我为什么它不工作吗 public class Main { static AtomicInteger counter = new AtomicInteger(0); public static void main(String[] args) { while(counter.getAndIncrement() < 10){ new Threa

嗨,我在试。我从主线程创建10个线程,并打印每个线程的静态计数器值

产量不确定。有人能告诉我为什么它不工作吗

public class Main {
    static AtomicInteger  counter = new AtomicInteger(0);

    public static void main(String[] args) {
        while(counter.getAndIncrement() < 10){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(counter.get());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}
我最讨厌的是

3 3 6 7 7 10 11 11

每次输出都不同。
我不希望它们按正确的顺序排列,但我希望它们的值在0到10之间是唯一的。

您有一个线程递增该值,多个线程获取并显示该值。显然,在递增线程执行它的任务时,存在很多潜在的问题,然后其余线程打印相同的值。调用start并不意味着线程将在值增加之前运行

相反,如果您将just get放入while循环,并在其他线程中使用incrementAndGet,那么您将获得唯一的值,尽管您可能会获得10个以上的值

如果您想要精确打印10个不同的值,那么代码将无法工作

使用原始代码,您可以创建10个线程,但当它们运行时,它们将打印计数器的当前值。如果启动的线程中有3个运行,它们将始终打印相同的值

当您将get移动到while循环中时,它可以并且将创建10个以上的线程,因为增量计数器的其他线程还没有机会运行,这导致在10个增量线程运行之前创建线程。在此之后,仍然有创建的线程,但尚未运行->您将获得10多个额外线程


如果要使用线程,则无法使用单个计数器变量获得所需的输出。

您有一个递增值的线程和多个获取并显示值的线程。显然,在递增线程执行它的任务时,存在很多潜在的问题,然后其余线程打印相同的值。调用start并不意味着线程将在值增加之前运行

相反,如果您将just get放入while循环,并在其他线程中使用incrementAndGet,那么您将获得唯一的值,尽管您可能会获得10个以上的值

如果您想要精确打印10个不同的值,那么代码将无法工作

使用原始代码,您可以创建10个线程,但当它们运行时,它们将打印计数器的当前值。如果启动的线程中有3个运行,它们将始终打印相同的值

当您将get移动到while循环中时,它可以并且将创建10个以上的线程,因为增量计数器的其他线程还没有机会运行,这导致在10个增量线程运行之前创建线程。在此之后,仍然有创建的线程,但尚未运行->您将获得10多个额外线程

如果要使用线程,则无法使用单个计数器变量获得所需的输出。

调用

counter.getAndIncrement();
之后在另一个线程调用中

System.out.println(counter.get());
那么这些值之间就没有任何关系了

如果要保留一个值,则需要在一个不变的变量中执行此操作

    for (int i = 0; i < 10; i++) {
        final threadId = i;
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(threadId);
            }
        }).start();
    }
不需要使用volatile变量,但如果确实需要,可以这样做

    for (int i = 0; i < 10; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(counter.getAndIncrement());
            }
        }).start();
    }
当你打电话的时候

counter.getAndIncrement();
之后在另一个线程调用中

System.out.println(counter.get());
那么这些值之间就没有任何关系了

如果要保留一个值,则需要在一个不变的变量中执行此操作

    for (int i = 0; i < 10; i++) {
        final threadId = i;
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(threadId);
            }
        }).start();
    }
不需要使用volatile变量,但如果确实需要,可以这样做

    for (int i = 0; i < 10; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(counter.getAndIncrement());
            }
        }).start();
    }

在一个线程中增加值,然后在另一个线程中获得值。你为什么期望它们是独一无二的?将getAndIncrement调用移到创建的线程中。谢谢keppil。好啊我还尝试了在run和get中使用getAndIncrement方法来检入while循环。在这种情况下,输出是按顺序进行的,但我的条件失败,它将打印10多个值。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16. 因此我把它改为上面的。你在一个线程中增加值,然后在另一个线程中得到值。你为什么期望它们是独一无二的?将getAndIncrement调用移到创建的线程中。谢谢keppil。好啊我还尝试了在run和get中使用getAndIncrement方法来检入while循环。在这种情况下,输出是按顺序进行的,但我的条件失败,它将打印10多个值。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16. 所以我把它改成上面的。我还尝试了在run和get中使用getAndIncrement方法来检入while循环。在这种情况下,输出是按顺序进行的,但我的条件失败,它将打印10多个值。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16. 我在下面的评论中使用了Peter Lawrey的建议,并使用了一个局部变量。效果很好。谢谢。我还尝试了在run和get中使用getAndIncrement方法来检入while循环。在这种情况下,输出是按顺序进行的,但是
我的条件失败,它将打印超过10个值。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16. 我在下面的评论中使用了Peter Lawrey的建议,并使用了一个局部变量。效果很好。谢谢,谢谢。使用局部变量有帮助。谢谢。使用局部变量有帮助。