线程通信的定义
线程是程序中独立的个体,但这些个体如果不经过处理就不能成为一个整体。线程间的通信就是使它们成为整体的方案之一。
可以说通过线程通信,线程之间的交互性会更强大,能够大大提高CPU的复用率,同时也可以对线程任务进行有效的把控和监督
轮询实现
import lombok.SneakyThrows;
import java.util.ArrayList;
import java.util.List;
/**
* 模拟厨师与服务员上菜
* @author layman
* @date 2021/2/7
*/
public class Demo10 {
public static void main(String[] args) {
Cook cook = new Cook();
WaiterA threadA = new WaiterA(cook);
threadA.start();
WaiterB threadB = new WaiterB(cook);
threadB.start();
}
}
class Cook {
//强制线程从公共堆栈获取数据
public volatile List<Integer> meal = new ArrayList();
public void add() throws InterruptedException {
for (int i = 1; i < 8 ; i++) {
meal.add(i);
System.out.println("第 "+i+" 道菜做好了");
Thread.sleep(1000);
}
}
}
class WaiterA extends Thread{
private Cook cook;
public WaiterA(Cook cook){
this.cook = cook;
}
@SneakyThrows
@Override
public void run() {
while (true){
cook.add();
}
}
}
class WaiterB extends Thread{
private Cook cook;
public WaiterB(Cook cook){
this.cook = cook;
}
@SneakyThrows
@Override
public void run() {
while (true){
if(cook.meal.size() == 5){
System.out.println("1号桌5个菜已经做好了,准备上菜");
throw new InterruptedException();
}
}
}
}
运行结果
结论
wait和notify实现
重点
: wait()会释放对象锁
wait方法
/**
* 测试wait()只能在同步方法中调用
*/
public class TestWait {
private String name = "layman";
public void methodA() throws InterruptedException{
name.wait();
}
public void methodB() throws InterruptedException {
synchronized (name){
name.wait();
}
}
public static void main(String[] args) throws InterruptedException {
TestWait tw = new TestWait();
tw.methodA(); //Exception in thread "main" java.lang.IllegalMonitorStateException
// tw.methodB();
}
}
nofify方法
import lombok.SneakyThrows;
public class Demo12 {
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
Demo12ThreadA threadA = new Demo12ThreadA(obj);
threadA.start();
//让主线程等待2秒钟
Thread.sleep(2000);
Demo12ThreadB threadB = new Demo12ThreadB(obj);
threadB.start();
}
}
class Demo12ThreadA extends Thread{
private Object lock;
public Demo12ThreadA(Object lock){
setName("A线程");
this.lock = lock;
}
@SneakyThrows
@Override
public void run() {
synchronized (lock){
System.out.println(Thread.currentThread().getName()+"进入等待,时间为:"+System.currentTimeMillis());
lock.wait();
System.out.println(Thread.currentThread().getName()+"结束等待,时间为:"+System.currentTimeMillis());
}
}
}
class Demo12ThreadB extends Thread{
private Object lock;
public Demo12ThreadB(Object lock){
setName("B线程");
this.lock = lock;
}
@SneakyThrows
@Override
public void run() {
synchronized (lock){
System.out.println(Thread.currentThread().getName()+"进行通知,时间为:"+System.currentTimeMillis());
lock.notify();
Thread.sleep(1000);
}
}
}
结论
- wait()
会
立刻释放对象锁,自身进入等待状态 - notify()
不会
立刻释放对象锁,当同步代码块执行完毕后才会释放
补充说明
sleep(long millis)与wait(long timeout)的区别:sleep不会释放对象锁,而wait会