研究生产者消费者
利用synchronized加互斥锁实现
package Consumer;
import java.util.Stack;
public class errorSolution {
public static void main(String[] args) {
Stack<Character> stack=new Stack<>();
Thread producer=new Thread(()->{
char c;
for(int i=0;i<10;i++) {
c=(char)(Math.random()*26+'A');
stack.push(c);
System.out.println("生产:"+c);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
Thread consumer=new Thread(()->{
char c;
for(int i=0;i<10;i++) {
c=stack.pop();
System.out.println("消费:"+c);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}
为什么无法消费呢?
说白了就是因为用了系统内的Stack,
当执行stack.pop();如果stack.isEmpty(),就会发生错误;
有人会说我们明明代码顺序是先生产再消费,
怎么会出现栈空呢?
这里就涉及到操作系统的知识了,简单来说,
进程中线程之间不断切换运行,由操作系统调度管理,而由于线程相互切换,又由操作系统管控,无法让它先生产后消费,依次完成,
怎么解决问题呢?
所以要重写Stack这个类,通过synchronized互斥锁解决。
伪代码(生产者——消费者)
核心代码——具体实现生产者消费者
package Consumer;
public class Stack {
private int pointer=0;
private char[] data=new char[5];
public synchronized void push(char c) {
// TODO 自动生成的方法存根
while(pointer==data.length) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
this.notify();
data[pointer]=c;
pointer++;
}
public synchronized char pop() {
// TODO 自动生成的方法存根
while(pointer==0) {
try {
this.wait();
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
this.notify();
pointer --;
return data[pointer];
}
}
实现
package Consumer;
public class Solution {
public static void main(String[] args) {
Stack stack=new Stack();
Thread producer=new Thread(()->{
char c;
for(int i=0;i<10;i++) {
//“*26”是为了控制随机生成范围为26个字母
c=(char)(Math.random()*26+'A');
stack.push(c);
System.out.println("生产:"+c);
try {
//每生产一个字符线程休眠一次,休眠时间( 0.0 to1.0)*1000
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
Thread consumer=new Thread(()->{
char c;
for(int i=0;i<10;i++) {
c=stack.pop();
System.out.println("消费:"+c);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
producer.start();
consumer.start();
}
}