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. CodeForces - 948C(前缀和 + 二分)

    链接:CodeForces - 948C 题意:N天,每天生产一堆雪体积 V[i] ,每天每堆雪融化 T[i],问每天融化了多少雪. 题解:对 T 求前缀和,求每一堆雪能熬过多少天,再记录一下多余的就 ...

  2. java设计模式之观察者模式以及在java中作用

    观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式.源-监听器(Source/Listener)模式或从属者(Dependen ...

  3. HDU 4722 Good Numbers(位数DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup2)

    Description If we sum up every digit of a number and the result can be exactly divided by 10, we say ...

  4. POJ 1703 Find them, Catch them(并查集拓展)

    Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...

  5. CubieTruck使用笔记--SD卡中使用lubuntu

    http://docs.cubieboard.org/tutorials/ct1/installation/install_lubuntu_desktop_server_to_sd_card 按照上面 ...

  6. await和async再学习

    await太不容易理解了,自己常常迷惑,不知道该怎么用. 文章:探索c#之Async.Await剖析 这篇文章,有一个很清晰的描述: 使用Async标记方法Async1为异步方法,用Await标记Ge ...

  7. CE-HTML简介

    1.典型的CE-HTML代码如下: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html ...

  8. Mac上利用Aria2加速百度网盘下载

    百度网盘下载东西的速度那叫一个慢,特别是大文件,看着所需时间几个小时以上,让人很不舒服,本文记录自己在mac上利用工具Aria2加速的教程,windows下思路也是一样! 科普(可以不看) 这里顺带科 ...

  9. elasticsearch 6.2.3安装ik分词

    下载 zip文件 上传到服务器 https://github.com/medcl/elasticsearch-analysis-ik/releases unzip elasticsearch-anal ...

  10. [C/C++] “箭头(->)”和“点号(.)”的区别

    转自:http://blog.csdn.net/gyymen/article/details/4962873 首先介绍一下C++中的结构.对于一个结构: struct MyStruct { int m ...