核心意思就是 现在没准备好,等我准备好了通知你啊。
比如你早上去找你女朋友,打电话说:亲爱的,下楼吧你女朋友说:等我一分钟哈
就这样你等了半小时,你女朋友轻轻的在背后拍了你一下:走我们去吃大餐吧~~
我们程序里对象太多了,所以对于有些对象就需要等待,等它准备好了再去做你想要做的事情。
本质就是 wait notify ,我们实际中用 notifyAll 就好了。在有就是这两个方法,必须在加锁的情况下才能用,不然会报错。
Exception in thread "小明" java.lang.IllegalMonitorStateExceptionat java.base/java.lang.Object.notifyAll(Native Method)at guarded_suspension.RequestQueue.putRequest(RequestQueue.java:25)at guarded_suspension.ClientThread.run(ClientThread.java:18)
这就设计到管程 monitor了。这个我们会在额外一章节中介绍。记住这个结论就好了。
举个栗子:
- Request
- RequestQueue
- ClientThread
- ServiceThread
- Main
public class Request {private String name;public Request(String name) {this.name = name;}public String getName() {return name;}@Overridepublic String toString() {return "Request{" +"name='" + name + '\'' +'}';}}
public class RequestQueue {private Queue<Request> requestQueue = new LinkedList<>();public synchronized Request getRequest() {while (requestQueue.peek() == null) {try {System.out.println("wait");wait();} catch (InterruptedException e) {e.printStackTrace();}}return requestQueue.remove();}public synchronized void putRequest(Request request) {requestQueue.add(request);notifyAll();System.out.println("notifyAll");}}
public class ClientThread extends Thread {private final RequestQueue requestQueue;public ClientThread(String name, RequestQueue requestQueue) {super(name);this.requestQueue = requestQueue;}@Overridepublic void run() {super.run();try {for (int i = 0; i < 10000; i++) {Request request = new Request("第 " + i + " 个 request");requestQueue.putRequest(request);Thread.sleep(3000);}} catch (InterruptedException e) {e.printStackTrace();}}}
public class ServiceThread extends Thread {private final RequestQueue requestQueue;public ServiceThread(String name, RequestQueue requestQueue) {super(name);this.requestQueue = requestQueue;}@Overridepublic void run() {super.run();try {for (int i = 0; i < 10000; i++) {Request request = requestQueue.getRequest();System.out.println(request.getName() + "---" + currentThread().getName());Thread.sleep(800);}} catch (InterruptedException e) {e.printStackTrace();}}}
public class Main {public static void main(String[] args){RequestQueue requestQueue = new RequestQueue();new ClientThread("小明",requestQueue).start();new ServiceThread("服务器端",requestQueue).start();}}
最后执行结果:
waitnotifyAll第 0 个 request---服务器端waitnotifyAll第 1 个 request---服务器端waitnotifyAll第 2 个 request---服务器端waitnotifyAll第 3 个 request---服务器端waitnotifyAll第 4 个 request---服务器端wait
当然我们平时不太会自己去写这么多代码,因为逻辑复杂了可能就会有潜在的问题,我们一般直接用 LinkedBlockingQueue 阻塞队列,直接 queue.take() 、queue.put(request) 并不需要 synchronize 也不需要 wait 、 notify,因为阻塞队列已经替我们做了。学会原理,再去用 java 系统的会更加丝滑呦~~
