例子

例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. 入门大数据---SparkSQL外部数据源

    一.简介 1.1 多数据源支持 Spark 支持以下六个核心数据源,同时 Spark 社区还提供了多达上百种数据源的读取方式,能够满足绝大部分使用场景. CSV JSON Parquet ORC JD ...

  2. Nginx 从入门到放弃(一)

    Nginx nginx的使用场景 静态资源服务 通过本地文件系统提供服务 反向代理服务 nginx的强大性能 缓存 负载均衡 API服务 OpenResty nginx优点 高并发.高性能 可扩展性好 ...

  3. 二.4vue展示用户数据及用户组操作以及给用户组添加额外字段

    一.用户列表 1.新建(1)views/users/index.vue: <template> <div class="user-list-container"& ...

  4. IE6浏览器有哪些常见的bug,以及解决IE6常用bug的方法

    1.IE6不支持min-height,解决办法使用css hack: .target { min-height: 100px; height: auto !important; height: 100 ...

  5. css3支持动画吗?css3可以用于网页动画的展现吗

    CSS3 主要可以分为几个模块:边框和背景,渐变,文字特效,字体,2D/3D转换,动画(过渡动画和动画),选择器,盒模型,多列布局,用户界面. css3动画有2类:一种是transition的,另一种 ...

  6. 一文说清 KubeSphere 容器平台的价值

    KubeSphere 作为云原生家族 后起之秀,开源近两年的时间以来收获了诸多用户与开发者的认可.本文通过大白话从零诠释 KubeSphere 的定位与价值,以及不同团队为什么会选择 KubeSphe ...

  7. 一口气说出 OAuth2.0 的四种鉴权方式,面试官会高看一眼

    本文收录在个人博客:www.chengxy-nds.top,技术资源共享,一起进步 上周我的自研开源项目开始破土动工了,<开源项目迈出第一步,10 选 1?页面模板成了第一个绊脚石 > , ...

  8. linux环境下安装 openOffice4并启动服务

    一.背景故事 openOffice是用来做office文档在线预览功能,把office文档转换成pdf交给前端显示. 之前系统开发过程一直没有将springboot服务怼上服务器,所以只安装了wind ...

  9. python 生成器(一):生成器基础(一)生成器函数

    前言 实现相同功能,但却符合 Python 习惯的方式是,用生成器函数代替SentenceIterator 类.示例 14-5 sentence_gen.py:使用生成器函数实现 Sentence 类 ...

  10. linux专题(二):走近Linux系统 (2020-04-08 10:08)

    http://dwz.date/UDf 走近Linux系统 开机登录 开机会启动许多程序.它们在Windows叫做"服务"(service),在Linux就叫做"守护进程 ...