1 等待唤醒机制
1.1举例说明
有三个角色,食客,厨师,桌子。两个线程食客和厨师。
厨师线程运行时,判断桌子上有没有饭,如果有则用wait()方法,让厨师线程等待,直至被其他线程唤醒,如果没有,则做饭放在桌子上,唤醒食客线程。
食客线程运行时如果有食物则吃掉,唤醒厨师线程来做,如果没有食物则用wait()方法让食客线程等待。
1.2普通代码实现
- 厨师
//角色食客
public class Foodie extends Thread{
@Override
public void run() {
while (true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
//桌子上没有食物
if(Desk.sign==0){
try {
//让这个线程等待。
Desk.lock.wait();//让当前线程与这个锁绑定
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
//桌子上有食物
System.out.println("食客在吃第"+Desk.count--+"碗,还能再吃"+Desk.count+"碗");
Desk.lock.notifyAll();//唤醒所右与这个锁绑定的线程,也就是厨师和食客,然后两者抢夺cpu,如果还是食客抢到了,则会执行上面的代码,
//让食客陷入次陷入等待。
Desk.sign=0;//修改桌子上食物的状态
}
}
}
}
}
}
- 食客
//角色厨师
public class Cookie extends Thread{
@Override
public void run() {
while (true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
//桌子上有食物
if(Desk.sign==1){
try {
//让这个线程等待。
Desk.lock.wait();//让当前线程与这个锁绑定
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
//桌子上没有食物
System.out.println("厨师在做第"+Desk.count+"碗");
Desk.lock.notifyAll();//唤醒所右与这个锁绑定的线程,也就是厨师和食客,然后两者抢夺cpu,如果还是食客抢到了,则会执行上面的代码,
//让食客陷入次陷入等待。
Desk.sign=1;//修改桌子上食物的状态
}
}
}
}
}
}
- 桌子和测试类
//桌子
public class Desk {
/**
* 一共来回多少次
*/
public static int count = 10;
/**
* 标记桌子上有没有食物
*/
public static int sign = 0;
/**
* 给厨师和食客的锁
*/
public static Lock lock=new ReentrantLock();
}
//测试类
public class TreadDemo {
public static void main(String[] args) {
Cook cook=new Cook();
Foodie foodie = new Foodie();
cook.start();
foodie.start();
}
}
1.3阻塞队列实现
1.3.1阻塞队列说明
-
ArrayBlockingQueue:底层是数组,有界。
- LinkedBlockingQueue:底层是链表,无界,但不是真正的无界,最大值为int的最大值。
- put()方法:当队列内数据满了时,放不进去,会等着,也叫阻塞。
- take()方法:取出第一个数据,取不到时会等着,也叫阻塞。
1.3.2阻塞队列细节说明
在put()和take()方法内部有使用锁来保护线程安全,不需要我们在方法外再使用锁来保护数据。他们是线程安全的。
1.3.3阻塞队列实现
//厨师
public class Cook extends Thread{
public static ArrayBlockingQueue<String> queue;
public Cook(ArrayBlockingQueue<String> queue){
this.queue=queue;
}
@Override
public void run() {
while (true){
try {
queue.put("面条");
System.out.println("厨师做了一个面条");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//食客
public class Foodie extends Thread{
public static ArrayBlockingQueue<String> queue;
public Foodie(ArrayBlockingQueue<String> queue){
this.queue=queue;
}
@Override
public void run() {
while (true) {
try {
String food = queue.take();
System.out.println("我吃了"+food);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//测试类
public class TreadDemo {
public static void main(String[] args) {
ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue<String>(1);//参数为阻塞队列的大小为1.
Cook cook=new Cook(arrayBlockingQueue);
Foodie foodie = new Foodie(arrayBlockingQueue);
cook.start();
foodie.start();
}
}