wait¬ify
wait方法的作用是使当前正在执行的线程进入等待状态,wait方法是Object类的方法,该方法用来将当前线程放入到“预执行队列”中,并且在wait所在的代码行进行停止执行,直到接到通知或被中断为止。在调用wait方法之前,线程必须获得该对象的对象锁,也就是说只能在同步方法或同步代码块中调用wait方法。在执行wait方法后,当前线程锁会自动释放,当wait方法返回该线程与其他线程重新竞争获取锁。
notify方法也是要在同步方法或者同步代码块中使用,在调用前必须获得对象的对象锁。这个方式是用来通知那些可能等待锁对象的其他线程,如果有多个线程等待,由线程调试器随机选一个wait状态的线程,向其发出通知,并使等待获取该对象的对象锁。
在执行notify方法后,当前线程不会马上释放该对象的对象锁,wait状态的线程也不能马上获取该对象的对象锁,要等到执行notify方法的线程将任务执行完成后,也就是退出synchronized代码块后,当前线程才会释放锁,wait状态的线程才可以获得锁。
一生产者一消费者
代码语言:javascript复制public class ThreadTest30 {
public static void main(String[] args) {
ThreadVo threadVo = new ThreadVo();
Thread producer = new ThreadProducer(threadVo);
producer.setName("生产者");
producer.start();
Thread consumer = new ThreadConsumer(threadVo);
consumer.setName("消费者");
consumer.start();
}
}
class ThreadProducer extends Thread{
private ThreadVo threadVo;
public ThreadProducer(ThreadVo threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.push(Math.random() "");
}
}
}
class ThreadConsumer extends Thread{
private ThreadVo threadVo;
public ThreadConsumer(ThreadVo threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.pop();
}
}
}
class ThreadVo {
private List<String> list = new ArrayList<>();
synchronized public void push(String val) {
try {
if (list.size() == 1) {
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
list.add(val);
System.out.println(Thread.currentThread().getName() "添加数据");
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
this.notify();
}catch (Exception e){
e.printStackTrace();
}
}
synchronized public String pop() {
String returnVal;
try {
if (list.size() == 0) {
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
returnVal = list.get(0);
list.remove(0);
System.out.println(Thread.currentThread().getName() ": 消费数据: " returnVal);
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
this.notify();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
执行结果:
生产者添加数据
生产者: 还有:1个数据
生产者等待中
消费者: 消费数据: 0.6627895017650591
消费者: 还有:0个数据
消费者等待中
生产者添加数据
生产者: 还有:1个数据
......
一生产者多消费者
代码语言:javascript复制public class ThreadTest31 {
public static void main(String[] args) {
ThreadVo31 threadVo = new ThreadVo31();
Thread producer = new ThreadProducer31(threadVo);
producer.setName("生产者");
producer.start();
Thread[] consumers = new Thread[5];
for (int i = 0; i < consumers.length; i ) {
consumers[i] = new ThreadConsumer31(threadVo);
consumers[i].setName("消费者" (char)('A' i));
consumers[i].start();
}
}
}
class ThreadProducer31 extends Thread{
private ThreadVo31 threadVo;
public ThreadProducer31(ThreadVo31 threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.push(Math.random() "");
}
}
}
class ThreadConsumer31 extends Thread{
private ThreadVo31 threadVo;
public ThreadConsumer31(ThreadVo31 threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.pop();
}
}
}
class ThreadVo31 {
private List<String> list = new ArrayList<>();
synchronized public void push(String val) {
try {
if (list.size() == 1) {
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
list.add(val);
System.out.println(Thread.currentThread().getName() "添加数据");
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
this.notify();
}catch (Exception e){
e.printStackTrace();
}
}
synchronized public String pop() {
String returnVal;
try {
while (list.size() == 0) { // 切记不可用if,容易导致虚假唤醒
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
returnVal = list.get(0);
list.remove(0);
System.out.println(Thread.currentThread().getName() ": 消费数据: " returnVal);
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
// 唤醒全部生产者
this.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
多生产者一消费者
代码语言:javascript复制public class ThreadTest32 {
public static void main(String[] args) {
ThreadVo32 threadVo = new ThreadVo32();
Thread[] producsers = new Thread[5];
for (int i = 0; i < producsers.length; i ) {
producsers[i] = new ThreadProducer32(threadVo);
producsers[i].setName("生产者" (char)('A' i));
producsers[i].start();
}
Thread consumer = new ThreadConsumer32(threadVo);
consumer.setName("消费者");
consumer.start();
}
}
class ThreadProducer32 extends Thread{
private ThreadVo32 threadVo;
public ThreadProducer32(ThreadVo32 threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.push(Math.random() "");
}
}
}
class ThreadConsumer32 extends Thread{
private ThreadVo32 threadVo;
public ThreadConsumer32(ThreadVo32 threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.pop();
}
}
}
class ThreadVo32 {
private List<String> list = new ArrayList<>();
synchronized public void push(String val) {
try {
while (list.size() == 1) { // 切记不可用if,容易导致虚假唤醒
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
list.add(val);
System.out.println(Thread.currentThread().getName() "添加数据");
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
this.notifyAll();
}catch (Exception e){
e.printStackTrace();
}
}
synchronized public String pop() {
String returnVal;
try {
while (list.size() == 0) {
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
returnVal = list.get(0);
list.remove(0);
System.out.println(Thread.currentThread().getName() ": 消费数据: " returnVal);
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
// 唤醒全部生产者
this.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
多生产者多消费者
代码语言:javascript复制public class ThreadTest33 {
public static void main(String[] args) {
ThreadVo33 threadVo = new ThreadVo33();
Thread[] producsers = new Thread[5];
Thread[] consumers = new Thread[5];
for (int i = 0; i < producsers.length; i ) {
producsers[i] = new ThreadProducer33(threadVo);
producsers[i].setName("生产者" (char)('A' i));
producsers[i].start();
consumers[i] = new ThreadConsumer33(threadVo);
consumers[i].setName("消费者" (char)('A' i));
consumers[i].start();
}
}
}
class ThreadProducer33 extends Thread{
private ThreadVo33 threadVo;
public ThreadProducer33(ThreadVo33 threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.push(Math.random() "");
}
}
}
class ThreadConsumer33 extends Thread{
private ThreadVo33 threadVo;
public ThreadConsumer33(ThreadVo33 threadVo) {
this.threadVo = threadVo;
}
@Override
public void run() {
while (true) {
threadVo.pop();
}
}
}
class ThreadVo33 {
private List<String> list = new ArrayList<>();
synchronized public void push(String val) {
try {
while (list.size() == 1) { // 切记不可用if,容易导致虚假唤醒
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
list.add(val);
System.out.println(Thread.currentThread().getName() "添加数据");
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
this.notifyAll();
}catch (Exception e){
e.printStackTrace();
}
}
synchronized public String pop() {
String returnVal;
try {
while (list.size() == 0) { // 切记不可用if,容易导致虚假唤醒
System.out.println(Thread.currentThread().getName() "等待中");
this.wait();
}
returnVal = list.get(0);
list.remove(0);
System.out.println(Thread.currentThread().getName() ": 消费数据: " returnVal);
System.out.println(Thread.currentThread().getName() ": 还有:" list.size() "个数据");
// 唤醒全部生产者
this.notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}