1. Introduce
In java, mutil-threads are used everywhere, applications not only take advantages of mutil-threads improving efficiency, but also encounter some confusing problems especially when threads are not synchronized correctly. Fortunately, java provides some basic primitives for synchronizing.
Producer-Consumer problem is a classic synchronization problem, in that situation a consumer is usually consuming util condition is not satisfied, then a producer starts to produce to make condition satisfied again, the consumer keeps waiting while producing.
2. wait() and notify()
Let's use wait() and notify() to illustrate producer-consumer problem. wait() and notify() are methods of Object class. Once a object's wait() is called, the current thread immediately suspends and waits until either another thread invokes notify() or notifyAll() method. Note that the current thread must own this obejct's monitor. The following codes will explain it.
Thread consumer = new Thread(){
@Override
public void run() {
// own blocker's monitor
synchronized (blocker){
while(true){
// wait for producer to produce product
blocker.wait();
// consume product until product is used out
while (product > 0){
product--;
System.out.println("consume one product ...");
}
}
}
}
};
Thread producer = new Thread(){
@Override
public void run() {
while(true){
// own blocker's monitor
synchronized (blocker){
// produce product when product is used out
if (product < 1){
product++;
System.out.println("produce one product ...");
}
// notice consumer to consume product
blocker.notify();
}
}
}
};
consumer.start();
producer.start();
Notice that in above codes, wait() is invoked within a loop[ while (product <= 0) ] that rechecks condition upon return, it is because that wait() may be waken up spuriously, a so-called spurious wakeup.
(For more information about spurious wakeup, see multithreading - Do spurious wakeups in Java actually happen? - Stack Overflow).
3. park() and unpark()
park() and unpark() are methods in LockSupport class, play a role similar to wait() and notify(), but a important difference is that park() and unpark() don't require any lock, an example of producer-consumer solution using park() and unpark() could be written as follows:
Thread consumer = new Thread(){
@Override
public void run() {
// block on blocker
while(true){
// wait for producer to produce product
while (product.get() <= 0){
LockSupport.park();
}
// consume product until product is used out
while (product.get() > 0){
product.decrementAndGet();;
System.out.println("consume one product ...");
}
}
}
};
Thread producer = new Thread(){
@Override
public void run() {
while(true){
// produce product when product is used out
if (product.get() < 1){
product.incrementAndGet();
System.out.println("produce one product ...");
}
// notice consumer to consume product
LockSupport.unpark(consumer);
}
}
};
consumer.start();
producer.start();
Note: Like wait(), park() could also be waken up spuriously, should be wrapped in a loop.
4. Difference
Compared to park() and unpark(), wait() and notify() have more limitions, for example:
1. notify() are limited to be after wait(), otherwise it will occur dead-lock.
2. The current thread must own the obejct's monitor before calling notify() and wait()
3. notify() chooses one thread arbitrarily to wake up if there are many threads waitting on the same object, while unpark() specifies which thread to be awakened.
👉👉👉 自己搭建的租房网站:全网租房助手,m.kuairent.com,每天新增 500+房源