核心意思就是 现在没准备好,等我准备好了通知你啊。

    比如你早上去找你女朋友,打电话说:亲爱的,下楼吧你女朋友说:等我一分钟哈
    就这样你等了半小时,你女朋友轻轻的在背后拍了你一下:走我们去吃大餐吧~~

    我们程序里对象太多了,所以对于有些对象就需要等待,等它准备好了再去做你想要做的事情。

    本质就是 wait notify ,我们实际中用 notifyAll 就好了。在有就是这两个方法,必须在加锁的情况下才能用,不然会报错。

    1. Exception in thread "小明" java.lang.IllegalMonitorStateException
    2. at java.base/java.lang.Object.notifyAll(Native Method)
    3. at guarded_suspension.RequestQueue.putRequest(RequestQueue.java:25)
    4. at guarded_suspension.ClientThread.run(ClientThread.java:18)

    这就设计到管程 monitor了。这个我们会在额外一章节中介绍。记住这个结论就好了。

    举个栗子:

    • Request
    • RequestQueue
    • ClientThread
    • ServiceThread
    • Main
    1. public class Request {
    2. private String name;
    3. public Request(String name) {
    4. this.name = name;
    5. }
    6. public String getName() {
    7. return name;
    8. }
    9. @Override
    10. public String toString() {
    11. return "Request{" +
    12. "name='" + name + '\'' +
    13. '}';
    14. }
    15. }
    1. public class RequestQueue {
    2. private Queue<Request> requestQueue = new LinkedList<>();
    3. public synchronized Request getRequest() {
    4. while (requestQueue.peek() == null) {
    5. try {
    6. System.out.println("wait");
    7. wait();
    8. } catch (InterruptedException e) {
    9. e.printStackTrace();
    10. }
    11. }
    12. return requestQueue.remove();
    13. }
    14. public synchronized void putRequest(Request request) {
    15. requestQueue.add(request);
    16. notifyAll();
    17. System.out.println("notifyAll");
    18. }
    19. }
    1. public class ClientThread extends Thread {
    2. private final RequestQueue requestQueue;
    3. public ClientThread(String name, RequestQueue requestQueue) {
    4. super(name);
    5. this.requestQueue = requestQueue;
    6. }
    7. @Override
    8. public void run() {
    9. super.run();
    10. try {
    11. for (int i = 0; i < 10000; i++) {
    12. Request request = new Request("第 " + i + " 个 request");
    13. requestQueue.putRequest(request);
    14. Thread.sleep(3000);
    15. }
    16. } catch (InterruptedException e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. }
    1. public class ServiceThread extends Thread {
    2. private final RequestQueue requestQueue;
    3. public ServiceThread(String name, RequestQueue requestQueue) {
    4. super(name);
    5. this.requestQueue = requestQueue;
    6. }
    7. @Override
    8. public void run() {
    9. super.run();
    10. try {
    11. for (int i = 0; i < 10000; i++) {
    12. Request request = requestQueue.getRequest();
    13. System.out.println(request.getName() + "---" + currentThread().getName());
    14. Thread.sleep(800);
    15. }
    16. } catch (InterruptedException e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. }
    1. public class Main {
    2. public static void main(String[] args){
    3. RequestQueue requestQueue = new RequestQueue();
    4. new ClientThread("小明",requestQueue).start();
    5. new ServiceThread("服务器端",requestQueue).start();
    6. }
    7. }

    最后执行结果:

    1. wait
    2. notifyAll
    3. 0 request---服务器端
    4. wait
    5. notifyAll
    6. 1 request---服务器端
    7. wait
    8. notifyAll
    9. 2 request---服务器端
    10. wait
    11. notifyAll
    12. 3 request---服务器端
    13. wait
    14. notifyAll
    15. 4 request---服务器端
    16. wait

    当然我们平时不太会自己去写这么多代码,因为逻辑复杂了可能就会有潜在的问题,我们一般直接用 LinkedBlockingQueue 阻塞队列,直接 queue.take() 、queue.put(request) 并不需要 synchronize 也不需要 wait 、 notify,因为阻塞队列已经替我们做了。学会原理,再去用 java 系统的会更加丝滑呦~~