等待无限循环完成。

huangapple go评论73阅读模式
英文:

Wait until infinite while loop is completed

问题

以下是翻译好的部分:

为什么setTestString方法没有等待?我做错了什么?

英文:

I have an infinite while loop which runs on another thread. In this while loop, I am using a String. 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.

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:

aaaaaaa
aaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
...

Actual output:

aaaaaaa
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
bbbbbbbb
...

Why is not the setTestString method waiting? What am I doing wrong?

答案1

得分: 1

问题在于你的线程每次都在读取更新后的实例变量。如果你希望循环的迭代看到一致的值,应该只读取实例变量的值一次。另外,由于你从一个线程写入它并从另一个线程读取它,你需要将它声明为volatile或者在同步方法内进行读写。

private volatile String testString = "aaaaaaa";

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

            System.out.println(localTestString);

            // 模拟线程阻塞操作
            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException exception) {
                exception.printStackTrace();
            }

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

> 当有人调用setter时我希望它等待当前循环迭代完成

这不是一个好的解决方案如果你让`set`方法等待不能保证它会在当前循环迭代完成后被调度你可以自己看到这一点`set`方法更改为

```java
private void setTestString(String testString) {
    synchronized (this.testString) {
        this.testString = testString;
    }
}
英文:

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

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. You can see it for yourself: change the set method to

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

huangapple
  • 本文由 发表于 2020年8月8日 19:00:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/63314617.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定