wait()注意以下几点:

1)wait()是属于Object类的方法。

2)调用了wait()之后会引起当前线程处于等待状态

3)将当前线程置入“预执行队列”中,并且在wait()所在的代码行处停止执行,直到接到通知或被中断为止。

4)在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步块中调用wait()方法。

5)执行wait()后,当前线程释放锁;从wait()返回前,线程与其他线程竞争重新获得锁。

6)如果调用wait()时没有持有适当的锁,则抛出IllegalMonitorStateException异常,它是RuntimeException的一个子类,所以,不需要try-catch语句进行捕捉。

7)当线程呈wait()状态时,调用线程对象的interrupt()方法会出现InterruptedException异常。

8)wait(1000)表示等待1000ms内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

notify()注意以下几点:

1)notify()方法可以让该线程重新处于活动(就绪)状态,从而去抢夺锁。

2)如果多个线程同时处于等待状态,那么调用notify()方法只能随机唤醒一个线程。

3)在同一时间内,只有一个线程能够获得锁,执行完毕之后,则再将其释放供其它线程抢占。

notifyAll()就是用来唤醒正在等待状态中的所有线程的:
(1)notifyAll()只会唤醒那些等待抢占指定对象锁的线程,其他线程则不会被唤醒。
(2)notifyAll()只会一个一个的唤醒,而并非统一唤醒。因为在同一时间内,只有一个线程能够持有对象锁。
(3)notifyAll()只是随机的唤醒线程,并非有序唤醒。
 
注意:执行notify()后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获得该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态所在的线程才可以获取该对象锁。当第一个获得了该对象锁的wait线程运行完毕以后,它会释放掉该对象锁,此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,还会继续组赛在wait状态,直到这个对象发出一个notify或notifyAll。
例子如下:
 //当list中的元素达到5个时发出通知notify
public class MyList {
private static List list = new ArrayList();
public static void add() {
list.add("aaa");
}
public static int size() {
return list.size();
}
}
//wait等待线程
public class WaitThread extends Thread{
private Object lock;
public WaitThread(Object lock) {
super();
this.lock = lock;
}
public void run() {
try {
synchronized(lock) {
if(MyList.size() != 5) {
System.out.println("wait begin:" + System.currentTimeMillis());
lock.wait();
System.out.println("wait end:" + System.currentTimeMillis());
}
}
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
//notify通知线程
public class NotifyThread extends Thread{
private Object lock;
public NotifyThread(Object lock) {
super();
this.lock = lock;
}
public void run() {
try {
synchronized(lock) {
for(int i = 0; i < 10; i++) {
MyList.add();
if(MyList.size() == 5) {
lock.notify();
System.out.println("已发出通知");
}
System.out.println("添加了" + (i + 1) + "个元素!");
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//测试线程
public class Main { public static void main(String[] args) {
try {
Object lock = new Object();
WaitThread wait = new WaitThread(lock);
wait.start();
Thread.sleep(50);
NotifyThread notify = new NotifyThread(lock);
notify.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

运行结果如下:

notify之后线程继续运行,并没有停止,而是把当前任务执行完后,才把锁由notify线程交给wait线程。

sleep()方法属于Thread类,从源码给出的解释来看,sleep()方法可以做到如下几点:

(1)首先,调用sleep()之后,会引起当前执行的线程进入暂时中断状态,也即睡眠状态。

(2)其次,虽然当前线程进入了睡眠状态,但是依然持有对象锁

(3)在中断完成之后,自动进入唤醒状态从而继续执行代码【wait(long)也可以实现这个功能】。

得出如下结论:

(1)在线程的运行过程中,调用该线程持有对象锁的wait()方法时,该线程首先会进入等待状态,并将自己持有的对象锁释放。

(2)如果一个线程正处于等待状态时,那么唤醒它的办法就是开启一个新的线程,通过notify()或者notifyAll()的方式去唤醒。当然,需要注意的一点就是,必须是同一个对象锁。

(3)sleep()方法虽然会使线程中断,但是不会将自己的monitor对象释放,在中断结束后,依然能够保持代码继续执行。

join()的例子:

 public class MyThread extends Thread{
public void run() {
try {
int secondValue = (int) (Math.random() * 10000);
System.out.println(secondValue);
Thread.sleep(secondValue);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main { public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
thread.join();
System.out.println("mythread对象执行完毕再执行");
} catch(InterruptedException e) {
e.printStackTrace();
}
} }

运行结果:

main线程等待了4476ms才开始执行,也就是等待对象线程执行完毕后才执行。

join()的作用:使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。能使线程由并行执行转为串行执行,具有同步的效果。

join与synchronized区别:join在内部使用wait()方法进行等待,而synchronized关键字使用的是“对象监视器”原理做为同步。

join(long)使用wait(long)来实现,所以是否释放锁,与wait(long)类似。

查看join的源码如下:

    public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0; if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
} if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

wait(),sleep(),notify(),join()的更多相关文章

  1. java多线程wait notify join

    wait notify 几个注意点: wait 与 notify/notifyAll 方法必须在同步代码块中使用,即要先对调用对象加锁. 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进 ...

  2. Java并发编程原理与实战二十一:线程通信wait&notify&join

    wait和notify wait和notify可以实现线程之间的通信,当一个线程执行不满足条件时可以调用wait方法将线程置为等待状态,当另一个线程执行到等待线程可以执行的条件时,调用notify可以 ...

  3. Java多线程技术-wait/notify/join

    wait/notify的作用 wait()方法的作用是使当前执行代码的线程进行等待,wait()是Object类的方法,用来将当前线程置入预执行队列中,并且在wait()所在的代码处停止执行,直到接到 ...

  4. java 线程 join(wait) 后,是如何唤醒

    概要:锁是线程,锁对象执行完毕后,会调用自身对象上的notify(); Join 方法:本质上还是根据wait方法实现的.分析join源码发现join方法本身是使用了synchronized修饰符的. ...

  5. 线程状态,BLOCKED和WAITING有什么区别

    线程可以通过notify,join,LockSupport.park方式进入wating状态,进入wating状态的线程等待唤醒(notify或notifyAll)才有机会获取cpu的时间片段来继续执 ...

  6. 【多线程】java多线程 测试例子 详解wait() sleep() notify() start() join()方法 等

    java实现多线程,有两种方法: 1>实现多线程,继承Thread,资源不能共享 2>实现多线程  实现Runnable接口,可以实现资源共享 *wait()方法 在哪个线程中调用 则当前 ...

  7. JAVA 多线程随笔 (二) sleep, yield, join, wait 和notify

    这里先说明一下锁对象,如果一个类比如Person里的方法都有synchronized来修饰,那么每一个方法的锁对象就是Person的一个实例person. 锁对象也可以针对某个特定的实例, 比如syn ...

  8. 【转】wait,notify,notifyAll,join,yield,sleep的区别和联系

    1.  Thread.sleep(long) 和Thread.yield()都是Thread类的静态方法,在调用的时候都是Thread.sleep(long)/Thread.yield()的方式进行调 ...

  9. java ---线程wait/notify/sleep/yield/join

    一.线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线 ...

随机推荐

  1. 剑指offer-树的子结构17

    题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) class Solution: def issubTree(self,pRoot1,pRoot2) ...

  2. JAVA课程设计——植物大战僵尸(团队)

    1.团队名称.团队成员介绍 团名:嗷嗷嗷嗷嗷 吴军霖(组长) 写得一手好代码也改得一手好bug 代码整洁好看源于强迫症 大概没有什么不会的东西叭 真正的王者段位 欧阳震霆(组员) 同样擅长写代码 在青 ...

  3. C++ Profiler工具之初体验

    http://www.cnblogs.com/likwo/archive/2012/12/20/2826988.html 转 http://www.cnblogs.com/lenolix/archiv ...

  4. Redis学习笔记之基础篇

    Redis是一款开源的日志型key-value数据库,目前主要用作缓存服务器使用. Redis官方并没有提供windows版本的服务器,不过微软官方开发了基于Windows的Redis服务器Micro ...

  5. 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组

    题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...

  6. 【bzoj1787】[Ahoi2008]Meet 紧急集合 倍增LCA

    题目描述 输入 输出 样例输入 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 6 6 6 样例输出 5 2 2 5 4 1 6 0 题解 倍增LCA 首先有集合点 ...

  7. CHM格式的电子书打开是空白的解决办法

    CHM是英语“Compiled Help Manual”的简写,即“已编译的帮助文件”.CHM是微软新一代的帮助文件格式,利用HTML作源文,把帮助内容以类似数据库的形式编译储存.

  8. hihocoder 1320 压缩字符串(字符串+dp)

    题解: 其实就是对应三种dp的转移方式 1.拼接类型 dp[i][j] = dp[i][c] + dp[c][j] 2.不变类型 dp[i][j] = j-i+1 3.重复类型(必须满足有k个循环节) ...

  9. EOS docker开发环境

    EOS Wiki提供了有关如何使用docker容器编译最新版本代码的说明.但可能有它自己的一些问题,因此我们鼓励你在学习时引用下面镜像.这样最初会更容易,更快. 如果你还没有安装docker,请在此处 ...

  10. [Leetcode] Multiply strings 字符串对应数字相乘

    Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...