多线程与并发-线程间通信

多线程与并发-线程间通信

概述:
多线程之间通信一般有这样几种方法:

  • 通过共享对象实现通信
  • wait/notify机制
  • Condition接口,await/signal机制
  • 消息队列,socket编程等网络通信

wait/notify机制

基础
前提:多个线程使用用一把锁,在使用wait(),notify(),notifyAll()之前要先获取当前对象的锁。

  • wait():运行至wait处时立刻阻塞当前线程,并释放锁。当被通知唤醒后开始竞争锁,如果获取到锁在继续向下执行。
  • notify():运行至notify处时立刻发送通知唤醒一个等待线程,但需要等到同步块运行结束之后才释放锁。
  • notifyAll():唤醒所有等待线程。
    其余方法
  • wait(long millis),时间到了相当于被通知,自动唤醒

实现
生产者消费者为例吧
单一缓存空间


public class A {
 private static String value;
 class MyService{
  private final String lock = new String("");
  private int i=0;
  public void produce(){
   synchronized (lock) {
    try {
     if(A.value!=null) {
      lock.wait();
     }
     A.value=" value = "+ i++;
     System.out.println("生产  :"+A.value);
     Thread.sleep(1000);
     lock.notify();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
  public void consume(){
   synchronized(lock) {
    try {
     if(A.value==null) {
      lock.wait();
     }
     System.out.println("消费  :"+A.value);
     A.value=null;
     Thread.sleep(1000);
     lock.notify();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
 }
 class ProduceThread extends Thread{
  private MyService service;
  ProduceThread(MyService service){
   this.service=service;
  }
  @Override
  public void run() {
   while(true) {
    service.produce();
   }
  }
 }
 class ConsumerThread extends Thread{
  private MyService service;
  ConsumerThread(MyService service){
   this.service=service;
  }
  @Override
  public void run() {
   while(true) {
    service.consume();
   }
  }
 }
 public static void main(String[] args) {
  A a = new A();
  MyService service = a.new MyService();
  a.new ProduceThread(service).start();
  a.new ConsumerThread(service).start();
  try {
   Thread.sleep(5000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.exit(0);
 }
}

缓存空间大于1


public class A {
 private static LinkedList<String> values = new LinkedList<>();
 private static final int SIZE = 5;
 class MyService{
  private final String lock = new String("");
  private int i=0;
  public void produce(){
   synchronized (lock) {
    try {
     while(A.values.size()==A.SIZE) {
      lock.wait();
     }
     String value =" value = "+ i++; 
     A.values.add(value);
     long id = Thread.currentThread().getId();
     System.out.printf("Thread %d 生产  :%s\n",id,value);
     lock.notifyAll();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  public void consume(){
   synchronized(lock) {
    try {
     while(A.values.size()==0) {
      lock.wait();
     }
     String value = A.values.poll();
     long id = Thread.currentThread().getId();
     System.out.printf("Thread %d 消费   :%s\n",id,value);
     lock.notifyAll();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   try {
    Thread.sleep(500);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   
  }
 }
 class ProduceThread extends Thread{
  private MyService service;
  ProduceThread(MyService service){
   this.service=service;
  }
  @Override
  public void run() {
   while(true) {
    service.produce();
   }
  }
 }
 class ConsumerThread extends Thread{
  private MyService service;
  ConsumerThread(MyService service){
   this.service=service;
  }
  @Override
  public void run() {
   while(true) {
    service.consume();
   }
  }
 }
 public static void main(String[] args) {
  A a = new A();
  MyService service = a.new MyService();
  
  List<Thread> threads = new ArrayList<>(); 
  for(int i=0;i<10;i++) {
   threads.add(a.new ProduceThread(service));
   threads.add(a.new ConsumerThread(service));
   
  }
  for(Thread thread : threads) {
   thread.start();
  }
  try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  System.exit(0);
 }
}

为不让单一线程完成所有生产或消费在外面休眠一定时间。
使用while与notifyAll避免假死现象出现(所有线程处于等待状态),原因:notify只通知一个线程,可能是同类型线程而非异构线程(生产者->消费者,消费者->生产者)
同时也可以通过while避免等待条件发生改变,避免过早通知问题

Condition

await/signal机制
await()与wait()类似
signal()与notify类似,但通知的是同一个Condition

一个Lock对象可以创建多个Condition条件。实现部分通知功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值