线程是操作系统中独立的个体,但是这些个体如果不经过特殊处理就不能成为一个整体,线程间通信就成为整体的必用方式之一。
使用wait/notify方法实现线程间的通信。这两个方法都是Object类的方法。
1.必须配合关键字synchronized使用;
2.wait方法释放锁,notify方法不释放锁。
以下是关于阿里的一道面试题,通过这道题,我们理解线程间通信。
示例:阅读以下代码,通过wait和notify方式对这个代码进行重构
import java.util.ArrayList;
import java.util.List;
public class ListAdd1 {
private volatile static List list = new ArrayList<>();
public void add(){
list.add(“wp”);
}
public int size(){
return list.size();
}
public static void main(String args[]){
final ListAdd1 l = new ListAdd1();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
for(int i=0;i<10;i++){
l.add();
System.out.println(“当前线程:”+Thread.currentThread().getName()+”添加了一个元素”);
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},”t1″);
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
if(list.size()==5){
System.out.println(“当前线程收到通知:”+Thread.currentThread().getName()+” list.size()==5 线程停止”);
throw new RuntimeException();
}
}
}
},”t2″);
t1.start();
t2.start();
}
}
结果:
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程收到通知:t2 list.size()==5 线程停止
Exception in thread “t2” java.lang.RuntimeException
at ListAdd1$2.run(ListAdd1.java:36)
at java.lang.Thread.run(Thread.java:745)
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
重构,改成wait和notify方式:
import java.util.ArrayList;
import java.util.List;
public class ListAdd2 {
private volatile static List list = new ArrayList<>();
final static Object lock = new Object();
public void add(){
list.add(“wp”);
}
public int size(){
return list.size();
}
public static void main(String args[]){
final ListAdd2 l = new ListAdd2();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock){
try {
for(int i=0;i<10;i++){
l.add();
System.out.println(“当前线程:”+Thread.currentThread().getName()+”添加了一个元素”);
Thread.sleep(500);
if(list.size()==5){
System.out.println(“已发出通知!”);
lock.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},”t1″);
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock){
if(list.size()!=5){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(“当前线程收到通知:”+Thread.currentThread().getName()+” list.size()==5 线程停止”);
throw new RuntimeException();
}
}
},”t2″);
t2.start();
t1.start();
}
}
结果:
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已发出通知!
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程收到通知:t2 list.size()==5 线程停止
Exception in thread “t2” java.lang.RuntimeException
at ListAdd2$2.run(ListAdd2.java:47)
at java.lang.Thread.run(Thread.java:745)
问题:有什么坏处?操作不是实时的。 解决方式:使用CountDownLatch实现实时通知。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class ListAdd2 {
private volatile static List list = new ArrayList<>();
final static Object lock = new Object();
final static CountDownLatch countDownLatch = new CountDownLatch(1);
public void add(){
list.add(“wp”);
}
public int size(){
return list.size();
}
public static void main(String args[]){
final ListAdd2 l = new ListAdd2();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
//synchronized(lock){
try {
for(int i=0;i<10;i++){
l.add();
System.out.println(“当前线程:”+Thread.currentThread().getName()+”添加了一个元素”);
Thread.sleep(500);
if(list.size()==5){
System.out.println(“已发出通知!”);
//lock.notify();
countDownLatch.countDown();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// }
}
},”t1″);
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
//synchronized(lock){
if(list.size()!=5){
try {
countDownLatch.await();
//lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(“当前线程收到通知:”+Thread.currentThread().getName()+” list.size()==5 线程停止”);
throw new RuntimeException();
// }
}
},”t2″);
t2.start();
t1.start();
}
}
结果:是实时的操作。
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
已发出通知!
当前线程:t1添加了一个元素
当前线程收到通知:t2 list.size()==5 线程停止
Exception in thread “t2” java.lang.RuntimeException
at ListAdd2$2.run(ListAdd2.java:51)
at java.lang.Thread.run(Thread.java:745)
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
当前线程:t1添加了一个元素
转载请注明来源网站:blog.ytso.com谢谢!
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/14700.html