我自己根据理解写了4种,可能会存在问题,望指正!
问题描述:
开5个线程,作为生产者线程,每个线程往容器里放3个;
开5个消费者线程,每个线程从容器里get3次;
如果容器满了,生产者阻塞;
如果容器空了,消费者阻塞。
1.用一个普通的数据结构如ArrayList来实现。
利用synchronized和Object自带的wait()/notifyAll()方法实现。
public static void main(String[] args) {
List<Integer> c=new ArrayList<Integer>(5);
//producer
for(int i=0;i<5;i++) {
new Thread(()->{
for(int j=0;j<3;j++) {
while(true) {
synchronized(c) {
if(c.size()<5) {
c.add(j);
System.out.println(Thread.currentThread().getName()+"product "+j);
c.notifyAll();
break;
}else {
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
},String.valueOf(i)).start();
}
for(int i=0;i<5;i++) {
new Thread(()->{
for(int j=0;j<3;j++) {
while(true) {
synchronized(c){
if(c.size()>0) {
int res=c.get(c.size()-1);
c.remove(c.size()-1);
System.out.println(Thread.currentThread().getName()+"comsume "+res);
c.notifyAll();
break;
}else {
try {
c.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
},String.valueOf(-i)).start();
}
}
在写的过程中遇到了java.lang.IllegalMonitorStateException,也记录下,这个Exception是在调用object的wait和notify,notifyAll方法的时候可能会出现的异常。注意wait/notify的方法要放在同步代码块或同步方法里(synchronized里)。
2.实现一个并发阻塞的容器
如果每次都需要用外部程序来实现一个生产者消费者的case,有点低效,所以如果实现一个容器来完成这些工作会更好。
class Container<T>{
private int cap;
private List<T> list=null;
public Container(int n) {
cap=n;
list=new ArrayList<>();
}
public synchronized boolean put(T n) {
while(true) {
if(list.size()<cap) {
list.add(n);
System.out.println(Thread.currentThread().getName()+"product "+n);
notifyAll();
break;
}else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return true;
}
public synchronized boolean take() {
while(true) {
if(list.size()>0) {
T res=list.get(list.size()-1);
list.remove(list.size()-1);
System.out.println(Thread.currentThread().getName()+"comsume "+res);
notifyAll();
break;
}else {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return true;
}
public int size() {
return list.size();
}
}
使用:
public static void main(String[] args) {
Container<Integer> c=new Container<>(5);
for(int i=0;i<5;i++) {
new Thread(()->{
for(int j=0;j<3;j++) {
c.put(j);
}
},String.valueOf(i)).start();
new Thread(()->{
for(int j=0