1.问题概述:
开辟一条线程代表生产者,开辟另一条线程代表消费者。生产者和消费者轮流生产和消费。生产和消费的数量使用随机数代替即可。生产者每次生产的产品数量+剩余的产品数量不能大于1000。
用到的方法:
(1)run()
定义线程中执行的内容。
(2)start()
表示开启线程,把当前的线程run();隔离成一个单独的任务。
(3)wait()
使线程进入等待状态,并且会释放被同步对象的锁。
(4) notify()
唤醒处于等待状态的线程。
2.代码实现
package thread;
// 开辟一条线程代表生产者,开辟另一条线程代表消费者。
// 生产者生产产品后,消费者进行消费。生产者和消费者轮流生产和消费。
// 生产和消费的数量使用随机数代替即可。生产者每次生产的产品数量+剩余的产品数量不能大于1000.
public class Demo {
public static void main(String[] args) {
Product p = new Product();
// 开辟新的线程去生产
new Thread(new Producter(p)).start();
// 开辟新的线程去消费
new Thread(new Consumer(p)).start();
}
}
// 消费者
class Consumer implements Runnable {
private Product p;
public Consumer(Product p) {
this.p = p;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (p) {
if (p.flag) {
try {
p.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 计算本次消费的数量
int count = (int) (Math.random() * (p.getCount() + 1));
// 提供剩余数量
p.setCount(p.getCount() - count);
System.out.println("本次消费的数量是" + count + ",剩余数量为" + p.getCount());
// 修改flag
p.flag = true;
// 唤醒线程
p.notify();
}
}
}
}
// 生产者
class Producter implements Runnable {
private Product p;
public Producter(Product p) {
this.p = p;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
synchronized (p) {
// 如果flag=false,表示需要消费,生产进程进入阻塞队列
if (!p.flag) {
try {
p.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 计算能够生产的最大数量
int max = 1000 - p.getCount();
// 实际生产的数量。Math的random()方法提供一个[0,1)之间的随机数。
// +1和强转为int类型的操作弥补了random方法不能提供随机数为1的不足。
int count = (int) (Math.random() * (max + 1));
// 可消费的商品量=此次产生的商品量加余下的商品
p.setCount(count + p.getCount());
System.out.println("本次实际生产的数量为" + count + ",本次提供的数量为" + p.getCount());
// 切换flag值
p.flag = false;
// 唤醒
p.notify();
}
}
}
}
// 产品
class Product {
// 代表商品数量
private int count;
// 如果flag是true,那么生产
// 如果flag是false,那么就消费
boolean flag = true;
// 获取商品数量
public int getCount() {
return count;
}
// 记录商品数量
public void setCount(int count) {
this.count = count;
}
}
3.运行结果
输出结果如下:
&:因为数值都是随机获取的,所以答案会有差异。只要套的起来就行了。
4.分析
创建两个子线程后,产生两种情况:
1.生产者线程先执行,程序运行步骤如下:
(1)执行同步块,获得资源p的锁。flag=true,跳过wait方法,生产产品,统计总量,输出,flag=false,执行notify方法,唤醒在阻塞队列中的线程(此时还没有在等待的线程)。回头执行while语句,true,执行同步块,获得资源p的锁,flag=false,执行wait方法,生产者线程进入阻塞状态,并立即释放CPU的控制权,释放资源p的锁。
(2)消费者线程执行run方法,执行同步块,获得资源p的锁。flag=false,,跳过wait方法。消费产品,统计总量,输出,flag=true,执行notify方法,唤醒在等待的生产者线程,释放资源p的锁。回头再进入同步块,获得资源p的锁,flag=true,执行wait方法,消费者线程进入阻塞状态,并立即释放CPU的控制权,释放资源p的锁。
(3)随后生产者线程获得资源p的锁,从上次阻塞的地方继续开始执行。生产产品,统计总量,输出,flag=false,执行notify方法,唤醒在等待的消费者线程。然后再生产者进程阻塞,消费者进程执行,如此一直反复下去,乐此不疲。
2.消费者线程先执行,程序运行步骤如下:
(1)run方法,执行同步块,获得资源p的锁,flag=true,消费者进程阻塞。生产者线程执行,run方法,执行同步块,获得资源p的锁。flag=true,跳过wait方法,生产产品,统计总量,输出,flag=false,执行notify方法,唤醒在阻塞队列中的消费者线程。
(2)回头执行while语句,true,执行同步块,获得资源p的锁,flag=false,执行wait方法,生产者线程进入阻塞状态,并立即释放CPU的控制权,释放资源p的锁。
(3)接情况1的步骤2.
以上内容为自己学习总结,仅供参考,若有不足
欢迎大家与我交流,一起学习,一起进步。