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. 配置SSH无密钥登陆(三)

    配置SSH无密钥登陆 (1).关闭防火墙 对每个虚拟机进行如下操作:   su    chkconfig  iptables  off 执行之后重启虚拟机:reboot (2).关闭之后,在maste ...

  2. 常见 SQL语句使用 增删改查

    一.常见的增删改查(一).查:1.SELECT 列名称 FROM 表名称,其中列名可以是多个,中间用豆号分开,如SELECT LastName,FirstName FROM Persons: 2.SE ...

  3. Spring框架(依赖注入)

    特点 1轻量级和侵入性低 2依赖注入和面向接口实现松耦合 3面向切面编程 减少样式代码 专有名词: 1依赖注入:对象无需自行管理依赖关系.通过系统负责协调在创建对象的第三方组件的设定,实现依赖关系自动 ...

  4. LaTex标准article文件框架解析

    新建一个LaTex-Article文件 生成的文件框架代码 % ---------------------------------------------------------------- % A ...

  5. lintcode-110-最小路径和

    110-最小路径和 给定一个只含非负整数的m*n网格,找到一条从左上角到右下角的可以使数字和最小的路径. 注意事项 你在同一时间只能向下或者向右移动一步 样例 标签 动态规划 思路 使用动态规划,用二 ...

  6. win7 Pthreads

    扩展地址 http://docs.php.net/manual/zh/book.pthreads.php 注意事项 php5.3或以上,且为线程安全版本.apache和php使用的编译器必须一致. 通 ...

  7. BZOJ4557 JLOI2016侦察守卫(树形dp)

    下称放置守卫的点为监控点.设f[i][j]为i子树中深度最大的未被监视点与i的距离不超过j时的最小代价,g[i][j]为i子树中距离i最近的监控点与i的距离不超过j且i子树内点全部被监视时的最小代价. ...

  8. poj 1753 Flip Game (dfs)

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 28805   Accepted: 12461 Descr ...

  9. 利用npm安装/删除/发布/更新/撤销发布包

    利用npm安装/删除/发布/更新/撤销发布包 什么是npm? npm是javascript的包管理工具,是前端模块化下的一个标志性产物 简单地地说,就是通过npm下载模块,复用已有的代码,提高工作效率 ...

  10. Codeforces Round #553 F Sonya and Informatics

    题目 题目大意 给定一个长为 $n$($2 \le n \le 100$)的01串 $S$ .对 $S$ 进行 $k$($1 \le k \le 10^9$)次操作:等概率地选取两个下标 $i, j$ ...