题目:写一个固定容量的同步容器,拥有put、get方法以及getCount方法,能够支持2个生产者以及10个消费者的阻塞调用。
思路
从题目可以得出这是一个同步容器,这就可以理解为该容器对象在调用过程中需要加锁,一般我们会想到synchornized,先用这个方法实现,下面是代码
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
public class Container<T> {
final private LinkedList<T> list=new LinkedList<T>();
final private int MAX=10;
private int count=0;
public synchronized void put(T t){
/*这里必须使用while,首先wait和while经常一起使用,其次如果使用if,会出现错误数据。
线程t一开始list.size()==MAX,线程t会wait,wait方法会释放锁.如果此时线程a执行get弄走一个数据,
然后线程b执行put方法,发现list.size()<MAX,然后执行add方法,这个时候数据就满了,即list.size()==MAX。
这个时候线程t被叫醒,接着wait后执行,如果这里是if的话线程t不会再去判断list.size()和MAX的大小
其实这里已经错了,这里的list.size()和MAX已经相等了,需要t去wait但是t线程没有while判断所以出错*/
while(list.size()==MAX){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
count++;
list.add(t);
this.notifyAll();
}
public synchronized T get(){
T t=null;
while(list.size()==0){
try {
this.wait(); //wait()释放锁
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
t=list.removeFirst();
count--;
this.notifyAll();
return t;
}
public int getCount(){
return count;
}
public static void main(String[] args) {
Container<String> myCon=new Container<String>();
//10个消费者线程
for (int i = 0; i < 10; i++) {
Runnable c=new Runnable() {
@Override
public void run() {
for (int j = 0; j < 5; j++) {
System.out.println(myCon.get());
}
}
};
new Thread(c,"c"+i).start();
}
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//2个生产者线程
for (int i = 0; i < 2; i++) {
Runnable p=new Runnable() {
@Override
public void run() {
for (int j = 0; j < 26; j++) {
myCon.put(Thread.currentThread().getName()+" "+j);
}
}
};
new Thread(p,"p"+i).start();
}
Runnable p=new Runnable() {
@Override
public void run() {
System.out.println(myCon.getCount());
}
};
new Thread(p,"count").start();
}
}
总结
这里做个笔记,我感觉面试可能会碰到,所以可以收藏看看。