线程的生产者消费者
线程的生产者消费者
新建一个产品Person
package cn.lucky.producer;
/**
* @author lucky
*/
public class Person {
private String name;
private int age;
public void push(String name, int age) {
this.name = name;
this.age = age;
}
public synchronized void pop() {
System.out.println(this.name + "---" + this.age);
}
}
新建生产者
package cn.lucky.producer;
/**
* @author lucky
*/
public class Producer implements Runnable{
Person p = null;
public Producer(Person p) {
this.p = p;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
if(i%2==0){
p.push("Tom",11);
}else {
p.push("Marry",21);
}
}
}
}
新建消费者
package cn.lucky.producer;
/**
* @author lucky
*/
public class Consumer implements Runnable{
Person p = null;
public Consumer(Person p) {
this.p = p;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
p.pop();
}
}
}
测试
package cn.lucky.producer;
/**
* @author lucky
*/
public class Test {
public static void main(String[] args) {
Person p = new Person();
Producer producer = new Producer(p);
Consumer consumer = new Consumer(p);
new Thread(new Runnable() {
@Override
public void run() {
producer.run();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
consumer.run();
}
}).start();
}
}
结果

我们发现,全是Marry,跟我们预期的Tom---11,Marry---21循环不一样。
我们加个线程休眠扩大一下现象。
package cn.lucky.producer;
/**
* @author lucky
*/
public class Person {
private String name;
private int age;
public void push(String name, int age) {
try {
Thread.sleep(10);
this.name = name;
this.age = age;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void pop() {
try {
Thread.sleep(10);
System.out.println(this.name + "---" + this.age);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

虽然出现了Tom---11,但是我们还是没有达到理想效果,要如何达到呢?
首先我们对生产消费加个锁
我们会发现要么全是Tom,要么全是Marry,要么一半连续出现Tom,一半连续Marry
同步锁池的概念就出现了:
同步锁池:同步锁必须选择多个线程共同的资源对象,而一个线程获得锁的时候,别的线程都在同步锁池等待获取锁;当那个线程释放同步锁了,其他线程便开始由CPU调度分配锁

这是Object类中的方法
wait():执行该方法的线程对象,释放同步锁,JVM会把该线程放到等待池中,等待其他线程唤醒该线程
notify():执行该方法的线程唤醒在等待池中等待的任意一个线程,把线程转到锁池中等待(注意锁池和等待池的区别)
notifyAll():执行该方法的线程唤醒在等待池中等待的所有线程,把线程转到锁池中等待。
注意:上述方法只能被同步监听锁对象来调用,这也是为啥wait() 和 notify()方法都在 Object 对象中,因为同步监听锁可以是任意对象,只不过必须是需要同步线程的共同对象即可,否则别的对象调用会报错:java.lang.IllegalMonitorStateException
代码如下:
package cn.lucky.producer;
/**
* @author lucky
*/
public class Person {
private String name;
private int age;
private boolean flag=true;
public synchronized void push(String name, int age) {
try {
while (!flag){
this.wait();
}
Thread.sleep(10);
this.name = name;
this.age = age;
flag=false;
this.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void pop() {
try {
while (flag){
this.wait();
}
Thread.sleep(10);
System.out.println(this.name + "---" + this.age);
flag=true;
this.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试结果:

完结!

浙公网安备 33010602011771号