本篇文章通过一个经典的例子:生产者,消费者的模拟,来讲述线程:
import java.util.LinkedList;
/**
* 生产消费者模拟
*
* @author Administrator
*
*/
public class Stoge {
// 仓库最大上线
private int MAX = 10;
// 仓库集合
private LinkedList<Object> list = new LinkedList<>();
public void addPro(Object object) {
synchronized (list) {
if (list.size() == MAX) {
System.out.println("仓库已经满了,不能生产");
try {
// 等待
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
// 已经生产
list.add(object);
System.out.println("生产了一个产品,当前可消费产品数是:" + list.size());
// 唤醒消费
list.notify();
}
}
}
public void rem(Object object) {
synchronized (list) {
if (list.size() == 0) {
System.out.println("仓库没有货物,请补充");
try {
list.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
list.remove();
System.out.println("消费了一个产品,剩余" + list.size());
// 消费一个产品之后需要通知生产产生产品
list.notifyAll();
}
}
}
public static void main(String[] args) {
Stoge stoge = new Stoge();
String time= System.currentTimeMillis() + "";
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
stoge.addPro(String.format("生产者:", time));
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
stoge.rem(String.format("消费者:", time));
}
}
}).start();
}
}
其实生产者消费者利用了java的线程锁和线程的wait、notifyAll来实现。
首先两个线程启动,生产者的线程负责生产产品并且存放在集合里面,那么这里有一个关键的条件就是生产到程度,需要停下来,并且去通知消费方去消费。
这里就是通过一个变量MAX 来控制生产的程度,当产品集合长度等于10的时候,我们的集合已经装满了(假定集合只能装10个产品),生产产品的线程需要等待别人唤醒它的时候,它才会继续生产。
如果没有装满就继续生产,并且唤醒消费者去消费,因为我已经生产了一个产品了,消费者可以去消费了。
同理,消费者也是样的原理:集合的产品如果为0了,那么它是不能在去消费的,需要通知唤醒生产者继续生产产品,消费者进行等待。
本例主体现的是线程去获取一个对象锁的时候,别的线程是不能在去操作这个对象,synchronized (list) 就是去获取list这个对象的锁,当前线程如果没有对list操作完,别的线程都是不能去操作list 的,直到本线程操作完,释放锁之后,其他线程才会去争夺锁