进程通信的概念:
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的比用方式之一。当线程存在通信指挥,系统间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对线程任务在处理的过程中进行有效的把控与监督。
使用wait/notify方法实现线程间的通信(注意这两个方法都是object的类的方法,所有对象都有这两个方法):
1.wait和notify必须配合synchronized关键字使用
2.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("haha");
}
public int size(){
return list.size();
}
public static void main(String args[]){
final ListAdd1 la = new ListAdd1();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
try {
for(int i = 0;i<=10;i++){
Thread.sleep(500);
la.add();
System.out.println("当前线程:" + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
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
Exception in thread "t2" 当前线程收到通知:t2,list的size=5 线程停止,抛出异常
java.lang.RuntimeException
at t07.ListAdd1$2.run(ListAdd1.java:48)
at java.lang.Thread.run(Thread.java:745)
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
要求:使用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("haha");
}
public int size(){
return list.size();
}
public static void main(String args[]){
final ListAdd1 la = new ListAdd1();
final Object lock = new Object();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
synchronized(lock){
try {
for(int i = 0;i<=10;i++){
Thread.sleep(500);
la.add();
System.out.println("当前线程:" + Thread.currentThread().getName());
if(la.size()==5){
lock.notify();
System.out.println("唤醒通知已发出");
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
},"t1");
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
synchronized(lock){
if(list.size()!=5){
try {
lock.wait();
System.out.println("当前线程收到通知:"+ Thread.currentThread().getName() +",list的size=5 线程停止,抛出异常");
throw new RuntimeException();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
},"t2");
t2.start();
t1.start();
}
}
输出结果:
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
唤醒通知已发出
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
当前线程:t1
Exception in thread "t2" java.lang.RuntimeException
at t07.ListAdd1$2.run(ListAdd1.java:57)
at java.lang.Thread.run(Thread.java:745)
当前线程收到通知:t2,list的size=5 线程停止,抛出异常
分析:
加了wait和notify之后,需要将t1,t2线程执行顺序换一下,保证t2先进入等待状态,然后t1线程再唤醒t2。由于wait方法会释放锁,在t2等待后,lock会被释放,t1得到锁后开始执行,等到list.size()==5的时候会唤醒t2线程,但notify方法不会释放锁,所以t2线程得不到lock对象锁,只有等t1线程全部执行完毕t2线程才能继续往下执行。
- 好像加了wait/notify方法得到的结果并不是原来的效果,此时可以使用countDownLatch方法。