1 wait和notify
首先需要注意的是wait和notify都不在thread里,而是在Object里為什么呢?
原因是因為:wait和notify的使用時針對鎖的,如果沒有synchronized,wait和notify也起不到線程通信的作用,而synchronized是對象鎖,是針對對象的,所以wait和notify放在Object里面顯得更合理。
- wait的作用
wait是讓當(dāng)前線程等待,特別需要注意的是wait之前肯定有synchronized也就是說當(dāng)前線程肯定已經(jīng)拿到鎖了,wait之后線程會立刻釋放鎖 - notify的作用
notify的作用是喚醒之前wait的線程,需要注意的是就算notify也不是立刻釋放鎖,而是等到synchronized執(zhí)行完了才釋放鎖
來看一個wait和notify的例子:
package com.yuxi;
/**
* Created by yuxi on 17/1/31.
*/
public class WaitDemo {
public static void main(String[] args) {
Object object = new Object();
MyThread myThread = new MyThread(object);
new Thread(myThread).start();
// new Thread(myThread).start();
//需要注意的是wait和notify都必須在synchronized里面,否則就會拋出異常
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object) {
System.out.println("因為wait釋放鎖了所有main線程可以立刻拿到" + Thread.currentThread().getName() + "..." + System.currentTimeMillis());
object.notify();
System.out.println("因為wait釋放鎖了所有main線程可以立刻拿到" + Thread.currentThread().getName() + "..." + System.currentTimeMillis());
}
}
static class MyThread implements Runnable {
private Object object;
public MyThread(Object object) {
this.object = object;
}
public void run() {
synchronized (object) {
try {
System.out.println("wait....." + Thread.currentThread().getName() + "..." + System.currentTimeMillis());
object.wait();
Thread.sleep(2000);
System.out.println("wait....." + Thread.currentThread().getName() + "..." + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
結(jié)果是:
wait.....Thread-0...1485911417379
因為wait釋放鎖了所有main線程可以立刻拿到main...1485911417380
因為wait釋放鎖了所有main線程可以立刻拿到main...1485911417380
wait.....Thread-0...1485911419384
從結(jié)果可以看出:
wait之后鎖肯定釋放,不然notify的synchronized是無法拿到鎖的。
2 wait和notify實例
來模擬一個線程通信的實例:
package com.yuxi;
/**
* Created by yuxi on 17/2/1.
*/
public class TxDemo {
public static void main(String[] args) {
Object object = new Object();
String name = "yuxi";
ThreadA threadA = new ThreadA(object,null);
ThreadB threadB = new ThreadB(object,name);
new Thread(threadA).start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(threadB).start();
}
static class ThreadA implements Runnable {
private Object object;
private String name;
public ThreadA(Object object, String name) {
this.object = object;
this.name = name;
}
public void run() {
try {
synchronized (object) {
if (name == null) {
System.out.println( Thread.currentThread().getName() + "..." + System.currentTimeMillis());
object.wait();
System.out.println("..."+Thread.currentThread().getName()+".....wait");
System.out.println( Thread.currentThread().getName() + "..." + System.currentTimeMillis());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class ThreadB implements Runnable {
private Object object;
private String name;
public ThreadB(Object object, String name) {
this.object = object;
this.name = name;
}
public void run() {
synchronized (object) {
if (name != null) {
System.out.println( Thread.currentThread().getName() + "..." + System.currentTimeMillis());
object.notify();
System.out.println("..."+Thread.currentThread().getName()+".....notify");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( Thread.currentThread().getName() + "..." + System.currentTimeMillis());
}
}
}
}
}
例子很簡單,一個線程A因為沒有值處于等待狀態(tài),另外一個線程B拿到值之后喚醒線程A,使得兩個線程直接完成通信。
結(jié)果:
Thread-0...1485913497377
Thread-1...1485913497481
...Thread-1.....notify
Thread-1...1485913502483
...Thread-0.....wait
Thread-0...1485913502483
3 wait和sleep,join區(qū)別
- 1 wait和yeild的區(qū)別
a: wait是讓線程進(jìn)入阻塞狀態(tài),yeild是讓線程進(jìn)入就緒狀態(tài)
b: wait之后是會釋放鎖的,而yeild是不會釋放鎖的。 - 2 wait 和sleep 的區(qū)別
wait和sleep都是讓線程進(jìn)入阻塞狀態(tài),區(qū)別是wait會釋放鎖,而sleep不會釋放鎖。