线程的通信
线程通信
线程的通信就是一个数据可以让两个线程轮流打印 你打印一下 我打印一下
线程的通信需要用到 wait() notify() 和 notifyAll()方法来使线程进行通信
通信方法:
wait() : 一旦执行此方法 当前线程就进入阻塞状态,并释放同步监视器(锁)
notify(): 一旦执行此方法,就会被唤醒的wait线程,如果有多个线程被wait就会唤醒优先级高的
notifuAll(): 一旦执行此方法释放所有被wait()方法阻塞的线程
说明:
说明: 1: wait() notify() notifyAll() 必须使用在同步代码块或者同步范方法中 2: 这三个方法必须都是同一个同步监视器调用
eg:
class ThreadTon implements Runnable{ private int num = 1; @Override public void run() { while (true){ synchronized(this){ notify(); // 让上一个阻塞的线程放开 if(num < 100){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" : "+num); num ++; try { ///调用方法是进来的线程进入阻塞状态, 执行wait会释放锁 一个线程执行了wait另一个就拿到了执行了 wait(); } catch (InterruptedException e) { e.printStackTrace(); } }else{ break; } } } } }
面试题:
面试题: sleep() 和wait()异同
相同:一旦执行都会使线程进入阻塞状态 不同点: 1: 两个方法的声明位置不同 Thread中声明sleep() Object中声明wait() 2: 调用的范围: sleep随时可以用, wait()必须使用在同步代码或者同步方法中 3: 是否释放同步监视器: 如果两个方法都是用在同步代码块和同步方法中 sleep()不会释放锁,wait()会释放锁
线程通信的经典例题: 生产者消费者
生产者(Productor)将产品交给店员(Clerk),而消费者(Customer)从店员处 取走产品, 店员一次只能持有固定数量的产品(比如:20), 如果生产者试图 生产更多的产品,店员会叫生产者停一下, 如果店中有空位放产品了再通 知生产者继续生产;如果店中没有产品了, 店员会告诉消费者等一下,如 果店中有产品了再通知消费者来取走产品。
首先我们要分析具体的信息
分析: 1; 是否有多线程问题? 是,生产者线程, 消费者线程 2: 是否有共享数据? 店员(或者产品) 3: 如何解决线程的安全问题? 同步机制三中方法 4: 是否涉及线程的通信
public class ProductTestOne { public static void main(String[] args) { ClerkOne clerkOne = new ClerkOne(); Consum c1 = new Consum(clerkOne); Produc p1 = new Produc(clerkOne); p1.start(); c1.start(); } } class ClerkOne{ // 商品 private int count = 0; // 记录商品的数量 public synchronized void consumPro() { // 消费方法 if(count > 0){ notify(); // 释放对方的线程 System.out.println(Thread.currentThread().getName() + " 开始消费第几个 : "+count); count --; }else{ // 等待 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void producPro() { // 生产 if(count < 20){ count ++; System.out.println(Thread.currentThread().getName() +" 开始生产第: "+count); notify(); }else{ // 等待 try { wait(); // 线程通信 } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consum extends Thread{ // 消费者 private ClerkOne clerkOne; public Consum(ClerkOne clerkOne){ this.clerkOne = clerkOne; } @Override public void run() { System.out.println("消费者开始消费"); while (true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerkOne.consumPro(); } } } class Produc extends Thread{ // 生产者 private ClerkOne clerkOne; public Produc (ClerkOne clerkOne){ this.clerkOne = clerkOne; } @Override public void run() { System.out.println("生产者开始生产"); while (true){ // sleep下 给生产消费留下余地 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerkOne.producPro(); } } }
.