例子

例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;

Object#wait()与Object#wait(long)的区别的更多相关文章

  1. JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  2. Java中的Object、T(泛型)、?区别

    因为最近重新看了泛型,又看了些反射,导致我对Object.T(以下代指泛型).?产生了疑惑. 我们先来试着理解一下Object类,学习Java的应该都知道Object是所有类的父类,注意:那么这就意味 ...

  3. [转] JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  4. Java不定参数Object… obj 和 Object[] 的区别

    Java不定参数Object… obj 和 Object[] 的区别 简述: java中方法重载可以实现参数不同自动匹配对应方法.但现实中也存在这种问题.普通传参对于形如下面的方法,却显得臃肿而失优雅 ...

  5. instanceof和isInstance(Object obj) 和isAssignableFrom(Class cls)的区别和联系

    instanceof和isInstance(Object obj) 和isAssignableFrom(Class cls)的区别和联系          编程的时候可能会遇到一个不知道它属于哪个类的 ...

  6. or in 、Object.keys()以及Object.getOwnPropertyNames有什么区别?

    or in .Object.keys()以及Object.getOwnPropertyNames的区别 var obj= Object.create(parent, { b: { value: 2, ...

  7. host Object和native Object的区别

    Native Object: JavaScript语言提供的不依赖于执行宿主的对象,其中一些是内建对象,如:Global.Math:一些是在脚本运行环境中创建来使用的,如:Array.Boolean. ...

  8. 小tips:JS之for in、Object.keys()和Object.getOwnPropertyNames()的区别

    for..in循环 使用for..in循环时,返回的是所有能够通过对象访问的.可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例.这里需要注意的是使用for-in返回的属性因各个浏览器厂 ...

  9. typeof 和 Object.prototype.toString.call 数据类型判断的区别

    使用 typeof 来判断数据类型,只能区分基本类型,即 “number”,”string”,”undefined”,”boolean”,”object” 五种. 但 Object.prototype ...

随机推荐

  1. Flask项目实战:创建电影网站(2)

    flask网站制作后台时候常见流程总结 安利一个神神器: 百度脑图PC版 创建数据库 下面是创建User数据库,需要导入db库 #coding:utf8 from flask import Flask ...

  2. Nuxt+Express后端api接口配置与实现方式

    Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用.本文带你了解在 Nuxt.js 中使用 Express 如何编写实现后端的 api 接口. 创建接口 ...

  3. Spring设置启动时执行方法

    @PostConstruct方法 在实现类和方法上加注解,类上加bean注解,方法上加@PostConstruct注解. @PostConstruct//启动执行public void refresh ...

  4. ORA-39257: Data cannot be remapped for more than 10 columns.

    ORA-39257: Data cannot be remapped for more than 10 columns. 前言 还是脱敏数据相关的事情. 使用expdp的remap_data参数对指定 ...

  5. IEEE754标准浮点格式

    两种基本浮点格式:单精度和双精度.IEEE单精度格式具有24位有效数字,并总共占用32 位.IEEE双精度格式具有53位有效数字精度,并总共占用64位 两种扩展浮点格式:单精度扩展和双精度扩展.此标准 ...

  6. 组合 a 标签与 canvas 实现图片资源的安全下载的方法与技巧

    普通用户下载图片时只需一个「右键另存为」操作即可完成,但当我们做在线编辑器.整个 UI 都被自定义实现时,如何解决不同域问题并实现页面中图片资源的安全下载呢?本文就解决该问题过程中所涉及的正则表达式. ...

  7. Scanner 类

    Java Scanner 类 java.util.Scanner 是 Java5的新特征,我们可以通过 Scanner 类来获取用户的输入. 基本语法: Scanner sc = new Scanne ...

  8. centos-docker安装及基本使用

    1.安装 1.安装之前 网络重启:service network restart 查看IP地址:ip addr 查看内核版本:uname -r 2.linux上安装docker 1.查看内核版本:un ...

  9. OAuth 2.0 授权方式讲解,规范实践和应用

    基于实践说规范 网上看了一些OAuth 2.0的授权方法,尽管讲解的没有什么逻辑性错误,但是存在一个问题,那就是单纯的讲解协议规范却脱离了实际的应用,缺少干货,所以才有了这篇文章,内容基于实际业务进行 ...

  10. JVM(完成度95%,不断更新)

    一.HotSpot HotSpot是最新的虚拟机,替代了JIT,提高Java的运行性能.Java原先是将源代码编译为字节码在虚拟机运行,HotSpot将常用的部分代码编译为本地代码. 对象创建过程 类 ...