作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想使用多线程(低级线程),但我遇到了问题。问题是,因为至少 wait 方法将被一个线程调用,而 notifyAll 将被另一个线程调用".
我的代码如下:
public class Reader extends Thread {
Calculator c;
public Reader(Calculator cal) {
c=cal;
}
public void run (){
synchronized(c) {
try {
System.out.println("Waiting for calculation");
c.wait();
} catch (InterruptedException ex) {}
System.out.println("Total is:" +c.total);
}
}
public static void main (String[] a) {
Calculator calculator=new Calculator();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
}
}
class Calculator implements Runnable {
int total;
public void run() {
synchronized(this) {
for(int i=0;i<100;i++) {
total=total+i;
}
notifyAll();
}
}
}
我在这里得到的输出是连续 5 次等待计算,所以我永远不会达到“总计就是总计”的说法。
我正在尝试找出解决问题的方法,但仍未找到解决方案。如果有人知道该怎么做,我将不胜感激。
提前致谢
最佳答案
您实际上并没有执行可运行的计算器,您拥有的代码不会计算总数或通知任何内容。使用计算器启动一个新线程:
new Thread(calculator).start();
在您初始化计算器局部变量的行之后。这将使计算器在主线程启动读者时开始工作。
仍然有可能计算器可能会在读者开始等待之前完成,而读者最终将永远等待永远不会到来的通知。创建一个条件变量,在这种情况下向计算器添加一个 boolean 标志,您将其初始化为 false 并在完成计算后设置为 true(通过 notifyAll,在离开同步块(synchronized block)之前)。让读者循环等待:
synchronized(c) {
try {
System.out.println("Waiting for calculation");
while (!c.finished) {
c.wait();
}
} catch (InterruptedException ex) {}
System.out.println("Total is:" +c.total);
}
这样,如果计算器在读者开始之前完成,读者将从条件变量中得知计算器已完成,他们不会等待。
总是在循环中调用 wait 方法是一个好习惯,因为
a) 当线程收到通知时,它没有锁,在线程收到通知和它重新获取锁之间的时间里,系统的状态可能会由于其他线程的操作而改变(不是本例中的情况)和
b) 你不能依赖等待的终止意味着线程收到了通知。
通过上述更改,程序正常完成并显示以下输出:
Waiting for calculation
Total is:4950
Waiting for calculation
Total is:4950
Waiting for calculation
Total is:4950
Waiting for calculation
Total is:4950
Waiting for calculation
Total is:4950
完整修改后的代码如下:
public class Reader extends Thread {
Calculator c;
public Reader(Calculator cal) {
c=cal;
}
public void run (){
synchronized(c) {
try {
System.out.println("Waiting for calculation");
while (!c.finished) {
c.wait();
}
} catch (InterruptedException ex) {}
System.out.println("Total is:" +c.total);
}
}
public static void main (String[] a) {
Calculator calculator=new Calculator();
new Thread(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
new Reader(calculator).start();
}
}
class Calculator implements Runnable {
int total;
boolean finished;
public void run() {
synchronized(this) {
finished = false;
for(int i=0;i<100;i++) {
total=total+i;
}
notifyAll();
finished = true;
}
}
}
关于java - 如何进行线程交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37733823/
我是一名优秀的程序员,十分优秀!