线程间通信,平时用到的并不多,但是理解其原理对多线程编程有很大的好处。这里编写了几个很简单的例子。
使用wait()和notify()注意
1、需要在 synchronized 包裹的代码块中。
2、wait()可以指定时间,如果没有,可能会导致线程一直等待。
样例:
@Slf4j
public class ThreadCommunicate {
public static void main(String[] args) {
ThreadCommunicate threadCommunicate = new ThreadCommunicate();
// //没有synchronized包裹的wait会报错
// threadCommunicate.waitTest1();
// //我等到永远,所以要注掉,不然下面没法走了
// threadCommunicate.waitTest2();
// //我等你5s
threadCommunicate.waitTest3();
// //没有synchronized包裹的notify会报错
threadCommunicate.notifyTest();
// //白雪公主与白马王子之间有一个电话
threadCommunicate.havePhone(threadCommunicate);
}
/**
* wait 需要在synchronized中才能正常使用
*/ public void waitTest1(){
log.info("白雪公主没给发出自己的地址,等待着王子的到来,会报错的。");
try {
wait();
} catch (Exception e) {
log.error("wait 必须在synchronized的包裹下,才能正常使用");
}
}
/**
* 无限等待
* synchronized 它可以把任意一个非 NULL 的对象当作锁。
*属于独占式的悲观锁,同时属于可重 入锁
*/ public synchronized void waitTest2(){
log.info("增加了synchronized,wait方法会把当前调用线程阻塞。相当于自己打晕了自己,给别人机会,当前 线程 是{}!" +
"可以看到系统一直处于运行状态无法停止,就像白雪公主永远等不到她的白马王子。",Thread.currentThread().getName());
try {
wait();
} catch (Exception e) {
log.info("wait 必须在synchronized的包裹下,才能正常使用");
e.printStackTrace();
}
}
/**
* 等你5s
*/ public synchronized void waitTest3(){
log.info("为了不永远的等待,这份约定增加了一个期限,如果5s内,你还没有和我道歉,那咱们就分手吧。当前线程是{}",Thread.currentThread().getName());
try {
wait(5000);
} catch (Exception e) {
log.info("wait 必须在synchronized的包裹下,才能正常使用");
e.printStackTrace();
}
log.info("5s过去了,白雪公主和白马王子分手了,勿念,祝越来越好。");
}
/**
* 用来当做对象锁
*/ public Object phone1 = new Object();
/**
* 在电话1中睡了
*/ public void waitWithPhone(){
synchronized (phone1){
log.info("在phone1包裹的synchronized中,白雪公主睡了。当前公主是{}。",Thread.currentThread().getName());
try {
phone1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("白雪公主接到了白马王子的电话,醒了。");
}
}
/**
* 打电话,吵醒白雪公主
*/ public void notifyWithPhone(){
synchronized (phone1){
log.info("在phone1包裹的synchronized中,白马王子来了。当前白马是{}。",Thread.currentThread().getName());
phone1.notify();
}
}
/**
* 有电话,两个线程才能通信
* @param threadCommunicate
*/ public void havePhone(ThreadCommunicate threadCommunicate){
Thread snowPrincess = new Thread(new Runnable() {
@ Override
public void run() {
threadCommunicate.waitWithPhone();
}
});
Thread horsePrice = new Thread(new Runnable() {
@Override
public void run() {
threadCommunicate.notifyWithPhone();
}
});
snowPrincess.start();
try {
Thread.sleep(100);
horsePrice.start();
Thread.sleep(1000);
log.info("白马王子顺利的通知了白雪公主,两个人过上了幸福的生活");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
样例可以直接在一个类文件中运行。