生产者消费者问题 - 找不到问题所在
Producer Consumer problem - can't find the what's wrong
我是 Java 的初学者,在 Java 中使用 多线程 尝试 生产者消费者 问题。
观察到的问题
- 一个线程没有执行,我找不到原因。
- 没有任何错误,但输出不匹配。
- 生产者线程是 运行,但消费者不是。
代码
所有 classes 都在一个文件中,导入:
import java.util.LinkedList;
import java.util.*;
为了便于阅读,我把它们分开了。
class fun {
LinkedList<Integer> list = new LinkedList<>();
int capacity=3;
synchronized void produce()throws InterruptedException {
int val=0;
while(true) {
while(list.size() == capacity) {
wait();
}
System.out.println("Producer Produced : "+val);
list.add(val);
val++;
notify();
}
}
synchronized void consume() throws InterruptedException {
while(true) {
while(list.size() == 0) {
wait();
}
int val;
val = list.removeFirst();
System.out.println("Consumer consumed-"+ val);
notify();
}
}
}
class a
定义一个线程:
class a extends Thread {
public void run() {
try {
fun obj=new fun();
obj.produce();
} catch(InterruptedException e) {
System.out.println(e);
}
}
}
class b
定义了另一个线程:
class b extends Thread {
public void run() {
try {
fun obj=new fun();
obj.consume();
} catch(InterruptedException e) {
System.out.println(e);
}
}
}
class pcp
包含 main
方法:
class pcp {
public static void main(String[]args) throws InterruptedException {
a t1=new a();
b t2=new b();
t1.start();
System.out.println(t1.isAlive());
t2.start();
System.out.println(t1.isAlive());
t1.join();
t2.join();
}
}
输出
C:\javaprogs>java pcp
true
true
Producer Produced : 0
Producer Produced : 1
Producer Produced : 2
我一直在检查我的 Java 代码有什么问题,但找不到任何答案。
您的 code/approach 的问题在于,您正在使用 class fun
的两个不同对象,理想情况下它们应该是多个线程之间的公共共享资源。
Inside class b
you are instantiating new object of fun
as
shown below
try{
fun obj=new fun();
obj.consume();
}
由于 class b
的实例从未共享过,因此总是会满足以下条件
while(list.size() == 0) {
wait();
}
并且不会有其他线程通知这个等待线程,因为您的生产者线程正在处理 a
的监视器;不是 b
。这导致您的生产者线程继续只打印上述内容。
现在,要解决这个问题,您可以按照以下步骤操作
- 考虑将
fun
声明为 class a
和 b
的成员
- 在
a
和 b
中提供构造函数,接受 fun
类型并使用成员变量初始化它
- 在
run()
方法中,尝试在 fun
成员变量 上调用 produce()
& consume()
- 最后一步是,在您的 main 中,创建一个
fun
的对象并使用它来创建 a
和 b
的实例
对您的代码进行一些修改后的完整代码如下所示。
import java.util.*;
public class pcp {
public static void main(String[] args) throws InterruptedException {
fun f = new fun();
a t1=new a(f);
b t2=new b(f);
t1.start();
System.out.println(t1.isAlive());
t2.start();
System.out.println(t1.isAlive());
t1.join();
t2.join();
}
}
class fun {
LinkedList<Integer> list = new LinkedList<>();
int capacity = 3;
synchronized void produce() throws InterruptedException {
int val = 0;
while (true) {
while (list.size() == capacity) {
wait();
}
System.out.println("Producer Produced : " + val);
list.add(val);
val++;
notify();
Thread.sleep(1000);
}
}
synchronized void consume() throws InterruptedException {
while (true) {
while (list.size() == 0) {
wait();
}
int val;
val = list.removeFirst();
System.out.println("Consumer consumed-" + val);
notify();
Thread.sleep(1000);
}
}
}
class a extends Thread {
fun f;
a(fun f) {
this.f = f;
}
public void run() {
try {
f.produce();
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
class b extends Thread {
fun f;
b(fun f) {
this.f = f;
}
public void run() {
try {
f.consume();
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
我是 Java 的初学者,在 Java 中使用 多线程 尝试 生产者消费者 问题。
观察到的问题
- 一个线程没有执行,我找不到原因。
- 没有任何错误,但输出不匹配。
- 生产者线程是 运行,但消费者不是。
代码
所有 classes 都在一个文件中,导入:
import java.util.LinkedList;
import java.util.*;
为了便于阅读,我把它们分开了。
class fun {
LinkedList<Integer> list = new LinkedList<>();
int capacity=3;
synchronized void produce()throws InterruptedException {
int val=0;
while(true) {
while(list.size() == capacity) {
wait();
}
System.out.println("Producer Produced : "+val);
list.add(val);
val++;
notify();
}
}
synchronized void consume() throws InterruptedException {
while(true) {
while(list.size() == 0) {
wait();
}
int val;
val = list.removeFirst();
System.out.println("Consumer consumed-"+ val);
notify();
}
}
}
class a
定义一个线程:
class a extends Thread {
public void run() {
try {
fun obj=new fun();
obj.produce();
} catch(InterruptedException e) {
System.out.println(e);
}
}
}
class b
定义了另一个线程:
class b extends Thread {
public void run() {
try {
fun obj=new fun();
obj.consume();
} catch(InterruptedException e) {
System.out.println(e);
}
}
}
class pcp
包含 main
方法:
class pcp {
public static void main(String[]args) throws InterruptedException {
a t1=new a();
b t2=new b();
t1.start();
System.out.println(t1.isAlive());
t2.start();
System.out.println(t1.isAlive());
t1.join();
t2.join();
}
}
输出
C:\javaprogs>java pcp
true
true
Producer Produced : 0
Producer Produced : 1
Producer Produced : 2
我一直在检查我的 Java 代码有什么问题,但找不到任何答案。
您的 code/approach 的问题在于,您正在使用 class fun
的两个不同对象,理想情况下它们应该是多个线程之间的公共共享资源。
Inside class
b
you are instantiating new object offun
as shown below
try{
fun obj=new fun();
obj.consume();
}
由于 class b
的实例从未共享过,因此总是会满足以下条件
while(list.size() == 0) {
wait();
}
并且不会有其他线程通知这个等待线程,因为您的生产者线程正在处理 a
的监视器;不是 b
。这导致您的生产者线程继续只打印上述内容。
现在,要解决这个问题,您可以按照以下步骤操作
- 考虑将
fun
声明为 classa
和b
的成员 - 在
a
和b
中提供构造函数,接受fun
类型并使用成员变量初始化它 - 在
run()
方法中,尝试在fun
成员变量 上调用 - 最后一步是,在您的 main 中,创建一个
fun
的对象并使用它来创建a
和b
的实例
produce()
& consume()
对您的代码进行一些修改后的完整代码如下所示。
import java.util.*;
public class pcp {
public static void main(String[] args) throws InterruptedException {
fun f = new fun();
a t1=new a(f);
b t2=new b(f);
t1.start();
System.out.println(t1.isAlive());
t2.start();
System.out.println(t1.isAlive());
t1.join();
t2.join();
}
}
class fun {
LinkedList<Integer> list = new LinkedList<>();
int capacity = 3;
synchronized void produce() throws InterruptedException {
int val = 0;
while (true) {
while (list.size() == capacity) {
wait();
}
System.out.println("Producer Produced : " + val);
list.add(val);
val++;
notify();
Thread.sleep(1000);
}
}
synchronized void consume() throws InterruptedException {
while (true) {
while (list.size() == 0) {
wait();
}
int val;
val = list.removeFirst();
System.out.println("Consumer consumed-" + val);
notify();
Thread.sleep(1000);
}
}
}
class a extends Thread {
fun f;
a(fun f) {
this.f = f;
}
public void run() {
try {
f.produce();
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
class b extends Thread {
fun f;
b(fun f) {
this.f = f;
}
public void run() {
try {
f.consume();
} catch (InterruptedException e) {
System.out.println(e);
}
}
}