一:2个生产者、10个消费者,自己定义一个容器,实现put、get方法wait notify+synchroized
- synchronized锁了这个对象,相当于实现了count变量的原子性,操作系统里面pv操作讲过
- wait方法不仅仅是进入阻塞队列阻塞,而且让出锁
- 注意1:条件是while不是if 2:notifyall不是notify
import java.util.LinkedList;
public class MyContainer<T> {
private LinkedList<T> lists = new LinkedList<T>();
private static final int MAX = 10;
private static int count = 0;
private synchronized void put(T t){
while(count==MAX){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lists.add(t);
++count;
System.out.println(Thread.currentThread().getName()+"放入一个。 count="+count);
this.notifyAll();
}
private synchronized T get(){
while(count==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T temp = lists.get(lists.size()-1);
--count;
System.out.println(Thread.currentThread().getName()+"拿走一个。 count="+count);
this.notifyAll();
return temp;
}
public static void main(String[] args) {
MyContainer<Object> container = new MyContainer<Object>();
//开启生产者
new Thread(()->container.put(new Object()),"thread1").start();
new Thread(()->container.put(new Object()),"thread2").start();
for(int i=0;i<10;i++){
new Thread(()->container.get(),"consumer"+i).start();
}
}
}
二:2个生产者、10个消费者,自己定义一个容器,实现put、get方法Condition+Renntrantlock。
比第一种方法有啥优点:
- 更容易处理异常。synchronized中间遇到异常会直接释放锁,线程会直接结束,假设一个线程只执行了一半,那就可能产生脏数据。使用Renntrantlock方便控制(lock.lock lock.unlock 碰到异常还可以自己先处理)。
- 效率更好。Condition相当于设置了两个等待队列,可以单独唤醒所有的消费者,或者单独唤醒所有的生产者。而第一种方式是唤醒所有的线程。
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyContainer2<T> {
private LinkedList<T> lists = new LinkedList<T>();
private static final int MAX = 10;
private static int count = 0;
private Lock lock = new ReentrantLock();
private Condition producer = lock.newCondition();
private Condition consumer = lock.newCondition();
private void put(T t){
try {
lock.lock();
while(lists.size()==MAX) {
producer.await();
}
System.out.println(Thread.currentThread().getName()+"放入一个");
lists.add(t);
count++;
consumer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private T get(){
T temp = null;
try{
lock.lock();
while(lists.size()==0){
consumer.await();
}
System.out.println(Thread.currentThread().getName()+"取走一个");
count--;
temp = lists.poll();
producer.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return temp;
}
public static void main(String[] args) {
MyContainer2<Object> container = new MyContainer2<Object>();
//开启生产者
new Thread(()->container.put(new Object()),"thread1").start();
new Thread(()->container.put(new Object()),"thread2").start();
for(int i=0;i<10;i++){
new Thread(()->container.get(),"consumer"+i).start();
}
}
}
111