1. 生产者与消费者
实现线程轮流交替执行的结果;
实现线程休眠和唤醒均要使用到锁对象;
修改标注位(foodFlag);
代码实现:
public class demo11 {
public static void main(String[] args) {
/**
* 需求:完成消费者和生产者(等待唤醒机制)的代码
* 实现线程轮流交替执行的结果
*/
Cooker cooker = new Cooker();
Foodie foodie = new Foodie();
cooker.setName("厨师");
foodie.setName("吃货");
cooker.start();
foodie.start();
}
}
class Cooker extends Thread {
@Override
public void run() {
/**
* 1.循环
* 2.同步代码快
* 3.判断共享数据是否到了末尾(到了末尾)
* 4.判断共享数据是否到了末尾(没到末尾,执行核心逻辑)
*/
while(true){
synchronized (Desk.lock){
if(Desk.count == 0){
break;
}else {
// 判断桌子上是否有食物
if(Desk.foodFlag == 1) {
// 如果有,就等待
try {
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else {
// 如果没有,就制作食物
System.out.println("厨师在制作面条");
// 修改桌子上的食物状态
Desk.foodFlag = 1;
// 叫醒等待的消费者开吃
Desk.lock.notifyAll();
}
}
}
}
}
}
class Foodie extends Thread {
@Override
public void run() {
/**
* 1.循环
* 2.同步代码快
* 3.判断共享数据是否到了末尾(到了末尾)
* 4.判断共享数据是否到了末尾(没到末尾,执行核心逻辑)
*/
while(true){
synchronized (Desk.lock) {
if(Desk.count == 0){
break;
}else {
// 先判断桌子上面是否有面条
if(Desk.foodFlag == 0) {
// 如果没有,就等待
// 不管是等待还是唤醒都是需要用锁对象进行处理的
try {
Desk.lock.wait(); // 让当前线程跟锁进行绑定
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else {
// 把吃的总数-1
Desk.count --;
// 如果有,就开吃
System.out.println("吃货在吃面条,还能再吃 " + Desk.count + "碗!");
// 吃完之后,就唤醒厨师继续做
Desk.lock.notifyAll();
// 最后要修改桌子的状态
Desk.foodFlag = 0;
}
}
}
}
}
}
class Desk extends Thread {
/**
* 作用:控制生产者和消费者的执行
*/
// 是否有面条 0:没有面条 1:有面条
public static int foodFlag = 0;
// 总个数
public static int count = 10;
// 锁对象
public static Object lock = new Object();
}
2. 使用阻塞队列实现
阻塞队列,当存入数据时,如果空间已满就阻塞;当取出数据时,如果没有数据在队列中就阻塞;
public class demo12 {
public static void main(String[] args) {
/**
* 需求:利用阻塞队列完成生产者和消费者
* 细节:
* 生产者和消费者必须使用同一个阻塞队列
*/
//1. 创建阻塞队列的对象
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);
//2. 创建线程的对象,并把阻塞队列传递过去
Cook12 cook12 = new Cook12(queue);
Foodie12 foodie12 = new Foodie12(queue);
cook12.start();
foodie12.start();
}
}
class Cook12 extends Thread {
//只定义,不给值
ArrayBlockingQueue<String> queue;
//让构造方法获取
public Cook12(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while(true){
//不断的把面条放到阻塞队列之中
try {
//ctrl+b进入源码
//put底层已经实现了锁,所以无需再写锁
queue.put("面条");
System.out.println("厨师做了面条");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
class Foodie12 extends Thread {
ArrayBlockingQueue<String> queue;
//让构造方法获取
public Foodie12(ArrayBlockingQueue<String> queue) {
this.queue = queue;
}
@Override
public void run() {
while(true){
//不断的从阻塞队列中获取面条
try {
//ctrl+b进入源码
//put底层已经实现了锁,所以无需再写锁
String take = queue.take();
System.out.println(take);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
3. 多线程的6种状态