线程间通信(线程间共享数据)

线程是操作系统中独立的个体,但这些个体之间相互通信才能成为一个整体。线程间的通信是成为整体的方案之一。

1. sleep()结合 while(true)死循环法实现多个线程间通信

虽然使用while(true)和sleep()结合在两个线程间实现了通信,但是不停的通过while(true)语句轮询机制来检测某一个条件,这样会浪费CPU资源。如果轮询的时间间隔很小,更浪费CPU资源;如果轮询的时间间隔很大,可能会取不到想要的数据。所以就需要有一种机制来减少CPU的资源浪费,而且还可以实现多个线程间通信,它就是wait/notify机制。

2. 等待/通知机制(重点)

  • wait()方法的作用是使当前执行代码的线程进行等待,wait()方法是Object类的方法,该方法用来将当前线程放入“预执行队列”中,并且在wait()方法所在的代码处停止执行,直到接到通知或者被中断为止。在调用wait()方法之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。在执行wait()方法后,当前线程释放锁。在从wait()方法返回前,线程与其他线程竞争重新获得锁。

  • notify()方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机挑选出其中一个wait()状态的线程,对其发出通知notify(),并使它等待获取该对象的对象锁。在执行notify()方法后,当前线程不会马上释放对象锁,wait()状态的线程也并不能马上获得当前的对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,这时wait()状态所在的线程才可以获取该对象锁。当第一个获得了该对象锁的wait()线程运行完之后,它会释放掉对象锁,此时如果没有对象再次使用notify()方法,则即便该对象已经空闲,其他wait()状态等待的线程由于没有得到该对象的通知,还会继续阻塞在wait()状态,直到这个对象发出一个notify()或notifyAll()。

总结:wait()使线程停止运行,而notify()使停止的线程继续执行。

  • wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒。
  • notify()方法可以随机唤醒“一个”等待同一个共享资源的线程,并使该线程退出等待队列,进入可运行状态,也就是notify()方法仅通知“一个”线程。
  • notifyAll()方法可以使“所有”处于等待同一共享资源的线程从等待状态退出,进入可运行状态。此时,优先级最高的那个线程最先执行,但也有可能是随机执行,这取决于JVM虚拟机的实现。

锁释放的时间(重点):

  • wait()方法执行后,锁被自动释放,不会执行wait()方法之后的代码。
  • notify()方法执行后,锁不会自动释放,必须执行完notify()方法所在的同步synchronized代码块后才释放锁
  • 在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被自动释放。

每个锁对象都有两个队列,一个是就绪队列,一个是阻塞队列。就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程。一个线程被唤醒后,才会进入就绪队列,等待CPU的调度;反之,一个线程被wait()后,就会进入阻塞队列,等待下一次唤醒。

3. 使用Condition和ReentrantLock实现等待/通知(线程间通信)

关键字synchronizedwait()notify()notifyAll()结合可以实现等待/通知模式(线程间通信),ReentrantLock类也可以实现相同的效果,但需要借助于Condition对象。Condition类是JDK1.5中出现的技术,在一个Lock对象中可以创建多个Condition实例,线程对象可以注册在指定的Condition中,用来实现有选择性的进行线程通知。这个功能是Condition类中默认提供的。

public class LockCondition {

    private Lock lock = new ReentrantLock();

    private Condition conditionA = lock.newCondition();
    private Condition conditionB = lock.newCondition();

    public void await_A(){
        lock.lock();
        try{
            //......
            conditionA.await();
            //......
        }catch(InterruptedException e){
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    public void await_B(){
        try{
            lock.lock();
            //......
            conditionB.await();
            //......
        }catch(InterruptedException e){
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }

    public void signal_A(){
        try{
            lock.lock();
          //......
            conditionA.signal();
        }finally{
            lock.unlock();
        }
    }

    public void signal_B(){
        try{
            lock.lock();
            //......
            conditionB.signal();
        }finally {
            lock.unlock();
        }
    }

}

说明:

  • Object类中的wait()方法相当于Condition类中的await()方法
  • Object类中的notify()方法相当于Condition类中的notify()方法
  • Object类中的notifyAll()方法相当于Condition类中的notifyAll()方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值