Java线程协作的两种方式

本文介绍了Java中线程协作的两种常见方式:一是利用Object类的wait(),notify()和notifyAll()方法,这些方法需要在同步块或同步方法中调用;二是使用java.util.concurrent包中的Condition接口,它与Lock接口配合使用,提供更安全高效的线程协作机制。Condition提供了await()和signal()方法,使得线程间的通信更具控制性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 介绍
    • Java中线程协作的最常见的两种方式:利用Object.wait()、Object.notify()和使用Condition
  • 方法一
    • Object中的wait、notify、notifyAll方法定义如下
    • public final native void notify(); public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException;
    • wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写
    • 调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)
    • 调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程
    • 调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程
    • 之所以这三个方法声明在Object类中是因为每个对象都拥有monitor(即锁)
    • 调用某个对象的wait()方法,当前线程必须拥有这个对象的monitor(即锁),因此调用wait()方法必须在同步块或者同步方法中进行
    • 示例
      • public class Test {
            public static Object object = new Object();
            public static void main(String[] args) {
                Thread1 thread1 = new Thread1();
                Thread2 thread2 = new Thread2();
                 
                thread1.start();
                 
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                 
                thread2.start();
            }
             
            static class Thread1 extends Thread{
                @Override
                public void run() {
                    synchronized (object) {
                        try {
                            object.wait();
                        } catch (InterruptedException e) {
                        }
                        System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");
                    }
                }
            }
             
            static class Thread2 extends Thread{
                @Override
                public void run() {
                    synchronized (object) {
                        object.notify();
                        System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()");
                    }
                    System.out.println("线程"+Thread.currentThread().getName()+"释放了锁");
                }
            }
        }

      • 运行结果
        • 线程Thread-1调用了object.notify()
          线程Thread-1释放了锁
          线程Thread-0获取到了锁       
  • 方法二
    • Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效
    • Condition是个接口,基本的方法就是await()和signal()方法
    • Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
    • 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
    • 示例
    • public class Test {
          private int queueSize = 10;
          private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
          private Lock lock = new ReentrantLock();
          private Condition notFull = lock.newCondition();
          private Condition notEmpty = lock.newCondition();
           
          public static void main(String[] args)  {
              Test test = new Test();
              Producer producer = test.new Producer();
              Consumer consumer = test.new Consumer();
                
              producer.start();
              consumer.start();
          }
            
          class Consumer extends Thread{
                
              @Override
              public void run() {
                  consume();
              }
                
              private void consume() {
                  while(true){
                      lock.lock();
                      try {
                          while(queue.size() == 0){
                              try {
                                  System.out.println("队列空,等待数据");
                                  notEmpty.await();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
                          queue.poll();                //每次移走队首元素
                          notFull.signal();
                          System.out.println("从队列取走一个元素,队列剩余"+queue.size()+"个元素");
                      } finally{
                          lock.unlock();
                      }
                  }
              }
          }
            
          class Producer extends Thread{
                
              @Override
              public void run() {
                  produce();
              }
                
              private void produce() {
                  while(true){
                      lock.lock();
                      try {
                          while(queue.size() == queueSize){
                              try {
                                  System.out.println("队列满,等待有空余空间");
                                  notFull.await();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
                          queue.offer(1);        //每次插入一个元素
                          notEmpty.signal();
                          System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
                      } finally{
                          lock.unlock();
                      }
                  }
              }
          }
      }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值