首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java多线程查询

Java多线程查询
EN

Stack Overflow用户
提问于 2019-01-03 10:28:27
回答 2查看 130关注 0票数 3

嗨,我是并发编程领域的新手,我正在测试下面的代码,并且was循环似乎没有终止线程。有人能帮我解释一下这里发生了什么吗。

代码语言:javascript
复制
public class PrimePrinter{
    public long counter = 0;
    public synchronized long getCounter() {
        return counter++;
    }
    public Thread makeThread() {
        Runnable rn = new Runnable() {          
            /* (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                while (counter < 100) {
                    try {
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName() + " : " +getCounter());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }                   
                }
            }
        };
        return new Thread(rn);
    }
    public static void main(String[] args) {
        int n = 10;
        Thread[] threads = new Thread[10];
        PrimePrinter pp = new PrimePrinter();
        for(int i = 1; i < n; i++) {            
            threads[i] = pp.makeThread();
            threads[i].start();
        }
    }
}

最后几行输出

代码语言:javascript
复制
Thread-4 : 81
Thread-5 : 87
Thread-7 : 91
Thread-5 : 97
Thread-2 : 95
Thread-4 : 98
Thread-6 : 96
Thread-8 : 90
Thread-1 : 93
Thread-3 : 92
Thread-0 : 94
Thread-2 : 99
Thread-6 : 107
Thread-3 : 103
Thread-0 : 104
Thread-1 : 105
Thread-8 : 106
Thread-5 : 102
Thread-4 : 101
Thread-7 : 100
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-03 10:35:33

每个线程在测试该counter < 100之后等待一秒钟,在这一秒内,其他线程可以增加计数器。

更新:您可以这样做:

代码语言:javascript
复制
            while (true) {
                long current = getCounter();
                if (current >= 100) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + " : " + current);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }                   
            }
票数 2
EN

Stack Overflow用户

发布于 2019-01-03 10:49:08

这并不是因为一个不可错过的关键原因。考虑一下代码实际运行的方式。它检查计数器值,然后休眠,然后打印,然后递增。

您有9个线程一次运行。然后,其中8个线程检查该值,此时,该值小于100。所以他们通过了测试继续前进。所有8人然后睡觉1000毫秒。同时,您的另一个线程刚刚增加了值.还有8人即将从睡梦中醒来。

因此,如果您的值是99 (这是不可避免的),那么您现在将从刚刚递增的线程中得到一个100的值。然后,已经通过测试的8也将递增,从而使计数器的结果值为108。

但是,要运行的最后一个线程将显示值107,因为您将打印所有运行的增量。

如果您以相反的方式这样做(如下面的代码所示),您将不会遇到这个问题。

以下代码工作正常:

代码语言:javascript
复制
public class PrimePrinter {
    public long counter = 0;

    public synchronized long getCounter() {
        return counter;
    }

    public synchronized void incrementCounter() {
        counter++;
    }

    public Thread makeThread() {
        Runnable rn = new Runnable() {
            /*
             * (non-Javadoc)
             * 
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                while (getCounter() < 100) {
                    try {
                        incrementCounter();
                        System.out.println(Thread.currentThread().getName()
                                + " : " + getCounter());
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        return new Thread(rn);
    }

    public static void main(String[] args) {
        int n = 10;
        Thread[] threads = new Thread[10];
        PrimePrinter pp = new PrimePrinter();
        for (int i = 1; i < n; i++) {
            threads[i] = pp.makeThread();
            threads[i].start();
        }
    }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54020445

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档