java多线程通信之等待唤醒机制
作者:网络转载 发布时间:[ 2017/3/15 10:16:59 ] 推荐标签:测试开发技术 Java
0、概述
多线程间通信,其实是多个线程操操作同一个资源,但是操作方式不同。典型实例有生产者和消费者,本文也通过实例来分析线程等待唤醒机制。
1、相关API介绍
public final void notify()
唤醒在此对象监视器上等待的单个线程,如果所有线程都在此对象上等待,则会任意选择唤醒其中一个线程。
public final void wait()
当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。
“为了实现监视器的排他性监视能力,JVM为每一个对象和类都关联一个锁;锁住了一个对象,是获得对象相关联的监视器”。
wait(),notify(),notifyAll(),这些方法都使用在同步代码块中,因为要对持有监视器的线程进行操作,所以要使用在同步中,因为只有同步才有锁。值得说明的是:等待和唤醒必须是同一个锁(必须为同一个对象)。由于锁可以是任意对象,所以可以被任意对象调用的方法定义在object类中。
2 、实例分析
仓库类
//等待和唤醒都是this锁
public class Storage<T> {
// 仓库大存储量
private final int MAX_SIZE = 1000;
private int storageSize = 100;
private Object[] data;
private int top = 0;
public Storage(int size) {
size = size <= 0 ? storageSize : size;
size = size > this.MAX_SIZE ? this.MAX_SIZE : size;
this.storageSize = size;
data = new Object[this.storageSize];
}
public int getStorageSize() {
return storageSize;
}
public synchronized T pop() {
while (top == 0) {
try {
//等待
wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
top--;
T t = (T) data[top];
//唤醒所有线程
notifyAll();
return t;
}
public synchronized void push(T t) {
while (top == storageSize) {
try {
wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
data[top++] = t;
notifyAll();
}
}
生产者
public class Producer implements Runnable {
private Storage<String> storage;
private volatile boolean breakLoop = false;
public Producer(Storage<String> storage) {
this.storage = storage;
}
@Override
public void run() {
int index = 1;
while (true) {
if (breakLoop) {
break;
}
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
storage.push("data:" + index);
System.out.println("Producer data:" + index);
index++;
}
}
public void destroy() {
this.breakLoop = true;
}
}
消费者
public class Consumer implements Runnable {
private Storage<String> storage;
private volatile boolean breakLoop = false;
public Consumer(Storage<String> storage) {
this.storage = storage;
}
@Override
public void run() {
while (true) {
if (breakLoop) {
break;
}
try {
Thread.sleep(1000);
} catch (Exception ex) {
ex.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "Consumer:" + storage.pop());
}
}
public void destroy() {
this.breakLoop = true;
}
}
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11