• Object#wait()与Object#wait(long)的区别


    例子

    例1 最基础的等待-通知

    下面一个例子,一个线程"waiting"在同步代码块调用了Object#wait()方法,另一个线程"timedWaiting"调用了Object#wait(3000)等待3000ms,主线程sleep 5000ms后唤醒所有线程。

    import java.util.concurrent.CompletableFuture;
    import java.util.concurrent.TimeUnit;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * @see Object#wait(long) 等待对应的毫秒数(不为0)或者被唤醒,执行后续代码
     * @see Object#wait() 只有被唤醒(底层源码调用wait 0 ms)才能执行后续代码
     * @author rhyme
     * @date 2020/5/30 11:38
     */
    @Slf4j
    public class ObjectWaitMain {
      private static final Object lock = new Object();
    
      private static final Runnable waiting =
          () -> {
            synchronized (lock) {
              try {
                log.info("Thread: {}, will Object#wait()", Thread.currentThread().getName());
                lock.wait();
                log.info("Thread: {} is notified.", Thread.currentThread().getName());
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
            }
          };
    
      private static final Runnable timedWaiting =
          () -> {
            synchronized (lock) {
              try {
                log.info(
                    "Thread: {}, will be notified or wait 3000 milliseconds.",
                    Thread.currentThread().getName());
                lock.wait(3000);
                log.info(
                    "Thread: {}, after being notified or wait 3000 milliseconds.",
                    Thread.currentThread().getName());
    
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
            }
          };
    
      public static void main(String[] args) throws InterruptedException {
    
        CompletableFuture.allOf(
            CompletableFuture.runAsync(waiting), CompletableFuture.runAsync(timedWaiting));
    
        // 主线程sleep5000ms,当3000ms后"timedWaiting"线程执行"wait(3000)"后的代码块
        // 如果"timedWaiting"线程在3000ms被notify,那么会立即执行后续代码,不会wait 3000ms
        TimeUnit.MILLISECONDS.sleep(5000);
    
        synchronized (lock) {
          log.info("main will notifyAll waiting thread.");
          lock.notifyAll();
        }
        log.info("main end.");
      }
    }

    执行结果:

    例2 Object#wait(long)的参数大于0与等于0

    测试类代码

    /**
     * @author rhyme
     * @date 2020/5/31 0:43
     */
    @Slf4j
    public class ThreadPoolExecutorTest {
      private ThreadPoolExecutor threadPoolExecutor;
    
      @Before
      public void initializeThreadPoolExecutor() {
        threadPoolExecutor =
            new ThreadPoolExecutor(4, 8, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(4));
      }
    
      @After
      public void teardown() throws InterruptedException {
        threadPoolExecutor.shutdown();
    
        TimeUnit.SECONDS.sleep(2);
        threadPoolExecutor = null;
      }

    大于0

    /**
       * 当 {@link Object#wait(long)}的参数是大于0, 线程wait对象的毫秒数后, 不需被唤醒, 就可再次获取锁执行wait后续代码
       * @see Object#wait(long)
       */
      @Test
      public void synchronizedTimedWaitingTest() {
        Runnable timedWaiting =
            () -> {
              synchronized (this) {
                while (true) {
                  try {
                    log.info("before Object#wait(1);");
                    this.wait(1);
                    log.info("after Object#wait(1);");
                  } catch (InterruptedException e) {
                    e.printStackTrace();
                  }
                }
              }
            };
    
        threadPoolExecutor.execute(timedWaiting);
      }

    执行结果:

    等于0或Object#wait()

    /**
       * 当 {@link Object#wait(long)}的参数是0, 线程只能是被唤醒后, 才能再次获取锁执行wait后续代码
       * @see Object#wait()
       */
      @Test
      public void synchronizedWaitingTest() {
        Runnable timedWaiting =
            () -> {
              synchronized (this) {
                while (true) {
                  try {
                    log.info("before Object#wait(0);");
                    // 与"this.wait()"等价
                    this.wait(0);
                    log.info("after Object#wait(0);");
                  } catch (InterruptedException e) {
                    e.printStackTrace();
                  }
                }
              }
            };
    
        threadPoolExecutor.execute(timedWaiting);
      }

    执行结果, 该线程一直wait, 线程池关闭结束, UT结束:

    总结

    Object#wait(long) 等待对应的毫秒数后(不为0)或者在等待过程中被唤醒后,就能再次获取锁执行wait后面代码;
    Object#wait() 只有被唤醒后(底层源码调用wait 0 ms)才能再次获取锁执行wait后面代码。

    源码如下:

    public final void wait() throws InterruptedException {
            wait(0);
    }
     public final native void wait(long timeout) throws InterruptedException;
  • 相关阅读:
    时刻记住 不要陷入碌碌无为中
    作战の计划
    SpringMVC确定目标方法POJO类型入参的过程
    springmvc框架第一帖HelloWorld
    Hibernate的主键生成策略的介绍
    Hibernate入门基本部署
    对于Hibernate框架的认识
    hibernate的第一个程序
    struts2框架的第一个程序
    java上传组件FileUpload
  • 原文地址:https://www.cnblogs.com/theRhyme/p/12992852.html
Copyright © 2020-2023  润新知