关于线程通信这块,一直处于一知半解的状态,没有进行系统全面的学习,看了前辈的博客后,按照自己的理解手敲了一遍,写篇博客记录一下,方便自己以后查阅复习。
- park/unpark
- volatile关键字
- synchronized + wait/notify
- countdownlatch
- condition + await/signal
1 park/unpark
package com.example.demo.demo;
import java.util.concurrent.locks.LockSupport;
/**
* @version V1.0
* @ClassName: ABDemo
* @Description: TODO
* @author: guoyiying
* @date 2020/1/7 9:28
*/
public class ABDemo {
public static void main(String[] args) {
Thread b = new Thread(new Runnable() {
@Override
public void run() {
LockSupport.park();
System.out.println("i am thread b, i am still alive.");
}
});
Thread a = new Thread(new Runnable() {
@Override
public void run() {
for(int i=1; i<11; i++){
System.out.println(i);
if(i==5){
LockSupport.unpark(b);
}
}
}
});
a.start();
b.start();
}
}
2 volatile关键字
package com.example.demo.demo;
/**
* @version V1.0
* @ClassName: wzl
* @Description: TODO
* @author: guoyiying
* @date 2020/1/7 9:28
*/
public class ABDemo {
private volatile static boolean flag = false;
public static void main(String[] args) {
Thread a = new Thread(new Runnable() {
@Override
public void run() {
for(int i=1; i<11; i++){
System.out.println(i);
if(i==5){
flag = true;
}
}
}
});
Thread b = new Thread(new Runnable() {
@Override
public void run() {
while(!flag){}
System.out.println("i am thread b, i am still alive.");
}
});
a.start();
b.start();
}
}
3 synchronized + wait/notify
注意:
- wait/notify关键字需搭配synchronized关键字食用
- 需先调用wait,再调用notify,否则会导致死锁,所以先启动线程b,再启动线程a
package com.example.demo.demo;
/**
* @version V1.0
* @ClassName:
* @Description: TODO
* @author: guoyiying
* @date 2020/1/7 10:53
*/
public class ABDemo {
private static Object object = new Object();
public static void main(String[] args) {
Thread a = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
for(int i=1; i<11; i++){
System.out.println(i);
if(i==5){
object.notify();
}
}
}
}
});
Thread b = new Thread(new Runnable() {
@Override
public void run() {
synchronized (object){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i am thread b, i am still alive.");
}
}
});
b.start();
a.start();
}
}
4 countdownlatch
每调用一次countDown
方法,计数器-1,减为0时,所有调用await
的代码将被唤醒。
package com.example.demo.demo;
import java.util.concurrent.CountDownLatch;
/**
* @version V1.0
* @ClassName:
* @Description: TODO
* @author: guoyiying
* @date 2020/1/7 10:57
*/
public class ABDemo {
private static CountDownLatch countDownLatch = new CountDownLatch(1);
public static void main(String[] args) {
Thread a = new Thread(new Runnable() {
@Override
public void run() {
for(int i=1; i<11; i++){
System.out.println(i);
if(i==5){
countDownLatch.countDown();
}
}
}
});
Thread b = new Thread(new Runnable() {
@Override
public void run() {
try {
countDownLatch.await();
System.out.println("i am thread b, i am still alive.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
a.start();
b.start();
}
}
5 condition + await/signal
注意:
- 同wait/notify,调用顺序可能会导致死锁
- 网上查了一下,说是await搭配signalAll可以避免死锁,亲测之后,发现还是会有死锁的出现
- 关于这点,还在学习当中,欢迎各位看官留言批评指正
package com.example.demo.demo;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @version V1.0
* @ClassName:
* @Description: TODO
* @author: guoyiying
* @date 2020/1/7 11:04
*/
public class ABDemo {
private static Lock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public static void main(String[] args) {
Thread a = new Thread(new Runnable() {
@Override
public void run() {
try{
lock.lock();
for(int i=1; i<11; i++){
System.out.println(i);
if(i==5){
condition.signalAll();
}
}
}finally {
lock.unlock();
}
}
});
Thread b = new Thread(new Runnable() {
@Override
public void run() {
try{
lock.lock();
try {
condition.await();
System.out.println("i am thread b, i am still alive.");
} catch (InterruptedException e) {
e.printStackTrace();
}}
finally {
lock.unlock();
}
}
});
b.start();
a.start();
}
}
参考文章
面试题:线程A打印1-10数字,打印到第5个数字时,通知线程B
结语
本人所有博客仅用于学习记录,不做任何商业用途,如涉及侵权,还请联系删除,感谢阅读,欢迎留言,一起进步~