简体   繁体   English

等到无限while循环完成

[英]Wait until infinite while loop is completed

I have an infinite while loop which runs on another thread.我有一个在另一个线程上运行的无限 while 循环。 In this while loop, I am using a String.在这个 while 循环中,我使用了一个字符串。 For this String, I also have a setter.对于这个字符串,我也有一个二传手。 When someone calls the setter, I want it to wait until the current iteration of the while loop finished and change it for the next iteration.当有人调用 setter 时,我希望它等到 while 循环的当前迭代完成并为下一次迭代更改它。

This is what I tried:这是我尝试过的:

import java.util.concurrent.TimeUnit;

public class Test {

    private String testString = "aaaaaaa";

    private Test() {
        new Thread(() -> {
            while (true) {
                synchronized (testString) {
                    System.out.println(testString);

                    // Simulating a thread blocking operation
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    } catch (InterruptedException exception) {
                        exception.printStackTrace();
                    }

                    System.out.println(testString);
                }
            }
        }).start();
    }

    private void setTestString(String testString) {
        synchronized (testString) {
            this.testString = testString;
        }
    }

    public static void main(String[] args) {
        Test test = new Test();

        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }

        test.setTestString("bbbbbbbb");
    }
}

Expected output:预期 output:

aaaaaaa
aaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
...

Actual output:实际 output:

aaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
...

Why is not the setTestString method waiting?为什么setTestString方法没有等待? What am I doing wrong?我究竟做错了什么?

The problem is that your thread is reading the updated instance variable every time.问题是您的线程每次都在读取更新的实例变量。 If you want the iteration of the loop see a consistent value, you should read the value of the instance variable only once.如果您希望循环的迭代看到一致的值,您应该只读取一次实例变量的值。 Also, since you are writing it from one thread and reading it from another, you need to make it volatile or do the read-write within synchronized methods.此外,由于您是从一个线程写入它并从另一个线程读取它,因此您需要使其易失或在同步方法中进行读写。

private volatile String testString = "aaaaaaa";

private Test() {
    new Thread(() -> {
        while (true) {
                // volatile read
                String localTestString = testString;

                System.out.println(localTestString);

                // Simulating a thread blocking operation
                try {
                    TimeUnit.SECONDS.sleep(10);
                } catch (InterruptedException exception) {
                    exception.printStackTrace();
                }

                System.out.println(localTestString);
        }
    }).start();
}

When someone calls the setter, I want it to wait until the current iteration of the while loop finished当有人调用 setter 时,我希望它等到 while 循环的当前迭代完成

That is not a good solution.这不是一个好的解决方案。 If you make the set method wait, there is no guarantee it gets scheduled after the current iteration of the loop is finished.如果您让 set 方法等待,则无法保证在循环的当前迭代完成后它会被调度。 You can see it for yourself: change the set method to你可以自己看:把set方法改成

private void setTestString(String testString) {
    synchronized (this.testString) {
        this.testString = testString;
    }
}

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

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