Collaboration between threads - wait, notify, notifyAll We introduced how to use wait, notify/notifyAll. Do you know if notify/notifyAll is actually used by a partner to wake up a wait thread?Let's take a look at the scene
Every holiday, I believe there will be many small partners to visit some scenic spots, but some scenic spots are too popular. For the sake of safety, the gardeners will limit the number of people entering the park.
Now suppose a park restricts only two people to enter, but if there are five tourists in total, we will have to queue them until the people inside come out and the people outside come in.How can we limit it?
We can certainly think first of what we've learned before Collaboration between threads - wait, notify, notifyAll Then we use wait, notify, and notifyAll methods to implement
First, let's define a scenic spot
public class Demo { public static final int MAX_SIZE = 2; //The total number of visitors to the garden public static int touristQty = 0; //Current number of visitors to the park public static int waitTouristQty = 0; //Current number of queued visitors }
And then we're defining our visitor class. There are two main ways to do that: to enter and leave the park
public class Tourist { public synchronized void into() { while (Demo.touristQty >= Demo.MAX_SIZE){ System.out.println("Please wait while the park is full" + ",There's more ahead" + Demo.waitTouristQty + "Visitors"); Demo.waitTouristQty++; try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("The current number of visitors to the park is:" + Demo.touristQty + ",Allow Entry"); Demo.touristQty++; if (Demo.waitTouristQty > 0) Demo.waitTouristQty--; } public synchronized void out() { System.out.println("Visitors leave the park"); Demo.touristQty--; if (Demo.waitTouristQty > 0) { notifyAll(); } } }
When visitors enter the park, we can judge if the maximum number of visitors in our park has reached. If not, we can enter the park and increase the number of visitors in the park by one. Otherwise, we will queue up and increase the number of queues by one. When some visitors leave the park, the number of visitors in the park will be reduced by one. We will see if any visitors are waiting to enter the park.Sometimes we tell them that someone is out and ready to garden.
And finally our test class
public class App { public static void main(String[] args) { for (int i = 0; i < 5; i++) { new TestThread().start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class TestThread extends Thread{ @Override public void run() { Tourist tourist = new Tourist(); tourist.into(); try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } tourist.out(); } }
Let's first look at the TestThread class of the test thread, and we created a visitor and allowed him to enter the park and leave after six seconds of play.
Then let's look at our test method above. Each minute, we create a threaded tourist, which takes 5 seconds to create 5 tourists. Then we should have the first two tourists in the park, the last three waiting in line, and when one of the tourists comes out, the queued tourists enter the park one by one, enter the park one by one, and finally complete it.Department exited.That's what we expected, and then we run the test class to see
We found that only the first two tourists left the park after their visit. The other three tourists seemed to have been waiting and not waking up. Why?
It should be noted at this point that our notify/notifyAll s are not threads that wake up all waits as we expected. Both notify() and notifyAll() work on objects, waking up other threads that are waiting for the same object lock.Are we the same person?Apparently not, we have five new threads, each with a new tourist.
Under the demonstration of the above problems, for example, today the gardener has a rest and will not let anyone enter the garden.
Then we add a user to the Tourist class, which is how we get special access
Then let's look at the test class
public class App { public static void main(String[] args) { Tourist tourist = new Tourist(); new Thread(tourist::into).start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(tourist::permit).start(); } }
This time we only new process one visitor, both threads are for the same object, and then we look at the results
This time our success woke up the waiting threads and let them play in the garden.
But our problem is still not completed, which is our initial need. Many tourists are visiting the park. How can we let them communicate with each other to inform other tourists that they are waiting to enter the park?See our concurrency tool class, Semaphore.