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. kaldi GMM模型解码指令 gmm-latgen-faster详解

    目录 - 作用: - 用法: - 可选项及含义: - 使用实例: - 作用: Generate lattices using GMM-based model. 生成基于GMM模型的lattice词格) ...

  2. MyBatis实例教程--开发环境搭建

    MyBatis实例教程--开发环境搭建 准备工作: 1.mybatis 的开发环境搭建,选择: eclipse j2ee 版本,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包 ...

  3. DFS——hdu1016Prime Ring Problem

    一.题目回顾 题目链接:Prime Ring Problem Problem Description A ring is compose of n circles as shown in diagra ...

  4. mac下使用clion构建boost库

    mac下使用clion构建boost库 使用brew install boost 完成后发现boost被安装在在/usr/local/Cellar/boost下 jetbrain给出的指导意见 htt ...

  5. beta版本冲刺四

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员:恺琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示组 ...

  6. 国内各运营商(ISP)IP段表

    国内各运营商(ISP)IP段表 来源:http://bbs.hh010.com/forum.php?mod=viewthread&tid=490529&orderby=dateline ...

  7. [洛谷P3834] 【模板】可持久化线段树 1(主席树)

    题目大意:静态区间第K小 题解:主席树 卡点:无 C++ Code: #include <cstdio> #include <algorithm> #define maxn 2 ...

  8. 【bzoj2064】分裂【压状dp】

    Description 背景: 和久必分,分久必和... 题目描述: 中国历史上上分分和和次数非常多..通读中国历史的WJMZBMR表示毫无压力. 同时经常搞OI的他把这个变成了一个数学模型. 假设中 ...

  9. [Leetcode] Populating next right pointer in each node 填充每个节点的右指针

    Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...

  10. 你是否彻底了解margin属性?

    写css,你少不了与margin打交道.你真的了解margin吗?你知道margin有什么特性吗?你知道什么是垂直外边距合并?margin在块元素.内联元素中的区别?什么时候该用padding而不是m ...