当前位置: 移动技术网 > IT编程>开发语言>Java > Java线程通信详解

Java线程通信详解

2019年07月22日  | 移动技术网IT编程  | 我要评论

焦媛伴我同行,情侣说,双增双节

线程通信用来保证线程协调运行,一般在做线程同步的时候才需要考虑线程通信的问题。

1、传统的线程通信

通常利用objeclt类提供的三个方法:

  1. wait() 导致当前线程等待,并释放该同步监视器的锁定,直到其它线程调用该同步监视器的notify()或者notifyall()方法唤醒线程。
  2. notify(),唤醒在此同步监视器上等待的线程,如果有多个会任意选择一个唤醒
  3. notifyall() 唤醒在此同步监视器上等待的所有线程,这些线程通过调度竞争资源后,某个线程获取此同步监视器的锁,然后得以运行。

这三个方法必须由同步监视器对象调用,分为两张情况:

同步方法时,由于同步监视器为this对象,所以可以直接调用这三个方法。

示例如下:

public class syncmethodthreadcommunication {
  static class datawrap{
    int data = 0;
    boolean flag = false;
    
    public synchronized void addthreada(){
      if (flag) {
        try {
          wait();
        } catch (interruptedexception e) {
          e.printstacktrace();
        }
      } 
      
      data++;
      system.out.println(thread.currentthread().getname() + " " + data);
      flag = true;
      notify();
    }
    
    public synchronized void addthreadb() {
      if (!flag) {
        try {
          wait();
        } catch (interruptedexception e) {
          e.printstacktrace();
        }
      } 
      
      data++;
      system.out.println(thread.currentthread().getname() + " " + data);
      flag = false;
      notify();
    }
  }
  
  static class threada extends thread {
    private datawrap data;
    
    public threada(datawrap datawrap) {
      this.data = datawrap;
    }
    
    @override
    public void run() {
      for (int i = 0; i < 10; i++) {
        data.addthreada();
      }
    }
  }
  
  static class threadb extends thread {
    private datawrap data;
    
    public threadb(datawrap datawrap) {
      this.data = datawrap;
    }
    
    @override
    public void run() {
      for (int i = 0; i < 10; i++) {
        data.addthreadb();
      }
    }
  }
  
  public static void main(string[] args) {
    //实现两个线程轮流对数据进行加一操作
    datawrap datawrap = new datawrap();
    
    new threada(datawrap).start();
    new threadb(datawrap).start();
  }

}

同步代码块时,需要使用监视器对象调用这三个方法。

示例如下:

public class syncblockthreadcomminication {
  static class datawrap{
    boolean flag;
    int data;
  }
  
  static class threada extends thread{
    datawrap datawrap;
    
    public threada(datawrap datawrap){
      this.datawrap = datawrap;
    }
    
    @override
    public void run() {
      for(int i = 0 ; i < 10; i++) {
        synchronized (datawrap) {
          if (datawrap.flag) {
            try {
              datawrap.wait();
            } catch (interruptedexception e) {
              e.printstacktrace();
            }
          }
          
          datawrap.data++;
          system.out.println(getname() + " " + datawrap.data);
          datawrap.flag = true;
          datawrap.notify();
        }  
      }
    }
  }
  
  static class threadb extends thread{
    datawrap datawrap;
    
    public threadb(datawrap datawrap){
      this.datawrap = datawrap;
    }
    
    @override
    public void run() {
      for (int i = 0; i < 10; i++) {
          synchronized (datawrap) {
            if (!datawrap.flag) {
              try {
                datawrap.wait();
              } catch (interruptedexception e) {
                e.printstacktrace();
              }
            }
            
            datawrap.data++;
            system.out.println(getname() + " " + datawrap.data);
            datawrap.flag = false;
            datawrap.notify();
          }
        }  
      }
      
  }
  public static void main(string[] args) {
    //实现两个线程轮流对数据进行加一操作
    
    datawrap datawrap = new datawrap();
    new threada(datawrap).start();
    new threadb(datawrap).start();
  }

}

2、使用condition控制线程通信

当使用lock对象保证同步时,则使用condition对象来保证协调。

示例如下:

import java.util.concurrent.locks.condition;
import java.util.concurrent.locks.lock;
import java.util.concurrent.locks.reentrantlock;

import com.sun.media.sound.riffinvaliddataexception;

import javafx.scene.chart.piechart.data;

public class synclockthreadcommunication {
  static class datawrap {
    int data;
    boolean flag;
    
    private final lock lock = new reentrantlock();
    private final condition condition = lock.newcondition();
    
    public void addthreada() {
      lock.lock();
      try {
        if (flag) {
          try {
            condition.await();
          } catch (interruptedexception e) {
            e.printstacktrace();
          }
        }
        
        data++;
        system.out.println(thread.currentthread().getname() + " " + data);
        flag = true;
        condition.signal();
      } finally {
        lock.unlock();
      }
    }
    
    public void addthreadb() {
      lock.lock();
      try {
        if (!flag) {
          try {
            condition.await();
          } catch (interruptedexception e) {
            e.printstacktrace();
          }
        }
        
        data++;
        system.out.println(thread.currentthread().getname() + " " + data);
        flag = false;
        condition.signal();
      } finally {
        lock.unlock();
      }
    }
  }
  
  static class threada extends thread{
    datawrap datawrap;
    
    public threada(datawrap datawrap) {
      this.datawrap = datawrap;
    }
    
    @override
    public void run() {
      for (int i = 0; i < 10; i++) {
        datawrap.addthreada();
      }
    }
  }
  
  static class threadb extends thread{
    datawrap datawrap;
    
    public threadb(datawrap datawrap) {
      this.datawrap = datawrap;
    }
    
    @override
    public void run() {
      for (int i = 0; i < 10; i++) {
        datawrap.addthreadb();
      }
    }
  }
  
  public static void main(string[] args) {
    //实现两个线程轮流对数据进行加一操作
    
    datawrap datawrap = new datawrap();
    new threada(datawrap).start();
    new threadb(datawrap).start();
  }

}

其中condition对象的await(), singal(),singalall()分别对应wait(),notify()和notifyall()方法。

3、使用阻塞队列blockingqueue控制线程通信

blockingqueue是queue接口的子接口,主要用来做线程通信使用,它具有一个特征:当生产者线程试图向blockingqueue中放入元素时,如果队列已满,则该线程被阻塞;当消费者线程试图从blockingqueue中取出元素时,如果队列已空,则该线程被阻塞。这两个特征分别对应两个支持阻塞的方法,put(e e)和take()

示例如下:

import java.util.concurrent.arrayblockingqueue;
import java.util.concurrent.blockingqueue;

public class blockingqueuethreadcomminication {
  static class datawrap{
    int data;
  }
  
  static class threada extends thread{
    private blockingqueue<datawrap> blockingqueue;
    
    public threada(blockingqueue<datawrap> blockingqueue, string name) {
      super(name);
      this.blockingqueue = blockingqueue;
    }
    
    @override
    public void run() {
      for (int i = 0; i < 100; i++) {
        try {
          datawrap datawrap = blockingqueue.take();
          
          datawrap.data++;
          system.out.println(getname() + " " + datawrap.data);
          sleep(1000);
        } catch (interruptedexception e) {
          e.printstacktrace();
        }
      }
    }
  }
  
  static class threadb extends thread{
    private blockingqueue<datawrap> blockingqueue;
    private datawrap datawrap;
    
    public threadb(blockingqueue<datawrap> blockingqueue, datawrap datawrap, string name) {
      super(name);
      this.blockingqueue = blockingqueue;
      this.datawrap = datawrap;
    }
    
    @override
    public void run() {
      for (int i = 0; i < 100; i++) {
        try {
          datawrap.data++;
          system.out.println(getname() + " " + datawrap.data);
          blockingqueue.put(datawrap);
          sleep(1000);
        } catch (interruptedexception e) {
          e.printstacktrace();
        }
      }
    }
  }
  
  public static void main(string[] args) {
    ///实现两个线程轮流对数据进行加一操作
    
    datawrap datawrap = new datawrap();
    blockingqueue<datawrap> blockingqueue = new arrayblockingqueue<>(1);
    
    new threada(blockingqueue, "consumer").start();
    new threadb(blockingqueue, datawrap, "producer").start();
  }

}

blockingqueue共有五个实现类:

arrayblockingqueue 基于数组实现的blockingqueue队列

linkedblockingqueue 基于链表实现的blockingqueue队列

priorityblockingqueue 中元素需实现comparable接口,其中元素的排序是按照comparator进行的定制排序。

synchronousqueue 同步队列,要求对该队列的存取操作必须是交替进行。

delayqueue 集合元素必须实现delay接口,队列中元素排序按照delay接口方法getdelay()的返回值进行排序。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网