例子

例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. 入门大数据---Spark累加器与广播变量

    一.简介 在 Spark 中,提供了两种类型的共享变量:累加器 (accumulator) 与广播变量 (broadcast variable): 累加器:用来对信息进行聚合,主要用于累计计数等场景: ...

  2. 洛谷P3694 邦邦的大合唱站队【状压dp】

    状压dp 应用思想,找准状态,多考虑状态和\(f\)答案数组的维数(这个题主要就是找出来状态如何转移) 题目背景 \(BanG Dream!\)里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. ...

  3. 初探numpy——广播和数组操作函数

    numpy广播(Broadcast) 若数组a,b形状相同,即a.shape==b.shape,那么a+b,a*b的结果就是对应数位的运算 import numpy as np a=np.array( ...

  4. 洛谷 P1828 【香甜的黄油 Sweet Butter】

    这道题应该就是模板题了吧qwq. 统计每一个牧场的放糖的情况,选择最优的即可 有亿点水的绿题. #include <bits/stdc++.h> using namespace std; ...

  5. SpringBoot-读取classpath下文件

    文章目录 开发过程中,必不可少的需要读取文件,对于打包方式的不同,还会存在一些坑,比如以jar包方式部署时,文件都存在于jar包中,某些读取方式在开发工程中都可行,但是打包后,由于文件被保存在jar中 ...

  6. 05 . k8s实战之部署PHP/JAVA网站

    传统部署和k8s部署区别 通常使用传统的部署的时候,我们一个web项目,网站的搭建,往往使用的如下的一种整体架构,可能有的公司在某一环节使用的东西是不一样,但是大体的框架流程是都是差不多的 1111 ...

  7. Python3笔记003 - 1.3 python开发工具

    第1章 认识python 1.3 python开发工具 IDLE(python自带的python shell) Pycharm(python开发的,选择专业版) 1.进入IDLE模式: C:\Prog ...

  8. Codeforces 1292C Xenon's Attack on the Gangs 题解

    题目 On another floor of the A.R.C. Markland-N, the young man Simon "Xenon" Jackson, takes a ...

  9. Least Cost Bracket Sequence,题解

    题目链接 题意: 给你一个含有(,),?的序列,每个?变成(或)有一定的花费,问变成课匹配的括号的最小花费. 分析: 首先如果能变成匹配的,那么就有右括号的个数始终不多于左括号且左右括号数量相等,那就 ...

  10. Docker-教你如何通过 Docker 快速搭建各种测试环境

    今天给大家分享的主题是,如何通过 Docker 快速搭建各种测试环境,本文列举的,也是作者在工作中经常用到的,其中包括 MySQL.Redis.Elasticsearch.MongoDB 安装步骤,通 ...