public class MyList {
/**
* 必须添加volatile修饰符,不然在线程中会一直取私有堆栈的值,公共堆栈的值改变后取不到
*/
volatile private List<String> list = new ArrayList<>();
public void addElement(){
list.add("咖啡");
}
public int getSize(){
return list.size();
}
}
public class MyThreadA extends Thread {
private MyList list;
private Object lock;
public MyThreadA(MyList list, Object lock) {
this.list = list;
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
try {
for (int i = 0; i < 10; i++) {
list.addElement();
System.out.println("已经添加了" + (i + 1) + "个元素了");
Thread.sleep(1000);
if (list.getSize() == 5){
//通知
lock.notify();
System.out.println("已发出通知了");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MyThreadB extends Thread {
private MyList list;
private Object lock;
public MyThreadB(MyList list, Object lock) {
this.list = list;
this.lock = lock;
}
@Override
public void run() {
synchronized (lock){
try {
PrintUtil.enterPrint("wait");
lock.wait();
PrintUtil.leavePrint("wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 个人理解:notify执行后发出通知,不过不会马上发出,需要当前方法执行完成之后才会发出,然后再有wait的方法接受的消息继续执行
*
* @Author: xjf
* @Date: 2019/6/7 8:57
*/
public class Main {
public static void main(String[] args) {
Object lock = new Object();
MyList list = new MyList();
//先运行threadB,让其进入等待状态
MyThreadB threadB = new MyThreadB(list,lock);
threadB.setName("B");
threadB.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MyThreadA threadA = new MyThreadA(list,lock);
threadA.setName("A");
threadA.start();
}
}
/**
* 打印工具类
* @Author: xjf
* @Date: 2019/6/4 8:44
*/
public class PrintUtil {
/**
* 进入方法时的打印
* @param methodName
*/
public static void enterPrint(String methodName){
System.out.println("threadName=[" + Thread.currentThread().getName() + "] enter into methodName=[" +
methodName + "]. time=" + TimeUtil.convertToString(System.currentTimeMillis()));
}
/**
* 离开方法时的打印
* @param methodName
*/
public static void leavePrint(String methodName){
System.out.println("threadName=[" + Thread.currentThread().getName() + "] leave methodName=[" +
methodName + "]. time=" + TimeUtil.convertToString(System.currentTimeMillis()));
}
}
threadName=[B] enter into methodName=[wait]. time=19-06-07 13:27:14
已经添加了1个元素了
已经添加了2个元素了
已经添加了3个元素了
已经添加了4个元素了
已经添加了5个元素了
已发出通知了
已经添加了6个元素了
已经添加了7个元素了
已经添加了8个元素了
已经添加了9个元素了
已经添加了10个元素了
threadName=[B] leave methodName=[wait]. time=19-06-07 13:27:25
Process finished with exit code 0
参考:《Java多线程编程核心技术》