线程等待与唤醒
标签: 多线程
基本方法简介
所有的等待和唤醒线程,都是针对某个具体
对象实例
的.
API接口 | 说明 |
---|---|
wait() | 让当前线程进入等待(阻塞)状态,直到其他线程调用此对象的notify()或notifyAll()来唤醒,之后该线程进入就绪状态. |
wait(long timeout) | 让当前线程进入阻塞状态,直到其他线程唤醒此线程或者 超过指定时间,之后该线程进入就绪状态 |
wait(long timeout,int nanos) | 让当前线程进入阻塞状态,直到其他线程唤醒此线程或者 超过指定时间或者 超过某个实际时间,之后该线程进入就绪状态 |
notify() | 唤醒该对象上的指定单个 线程 |
notifyAll() | 唤醒该对象上的所有 线程 |
wait() and notify() demo
package cn.kkcoder.thread;
public class WaitAndNotify {
public static void main(String[] args) throws InterruptedException {
notifyThread t = new notifyThread("t1");
synchronized(t) {
System.out.println(Thread.currentThread().getName() + " .start()");
t.start();
System.out.println(Thread.currentThread().getName() + " .wait()");
t.wait();
System.out.println(Thread.currentThread().getName() + " .结束");
}
}
}
class notifyThread extends Thread{
public notifyThread(String name) {
super(name);
}
@Override
public void run() {
synchronized(this) {
System.out.println(Thread.currentThread().getName() + " call notify()");
notify();
}
}
}
控制台:
main .start()
main .wait()
t1 call notify()
main .结束
总结
: wait() 方法是指让当前线程等待,并释放对象锁, 而此时的当前线程是 主线程,因为主线程获取了对象 t 的锁,t.start()之后,新建线程t1,并进入就绪状态,但是此时锁在 main 线程中,所以t1的run方法不执行,当t.wait()之后,当前线程(即主线程)进入等待(阻塞)状态,并释放t线程锁,于是执行run方法,唤醒等待的main线程,并且线程t1释放锁进入死亡状态.main线程继续执行.
tips:wait()指当先线程进入等待状态.
wait() and notifyAll() demo
package cn.kkcoder.thread;
public class NotifyAll {
static Object obj = new Object();
public static void main(String[] args) {
NotifyAllClass t1 = new NotifyAllClass("t1");
NotifyAllClass t2 = new NotifyAllClass("t2");
NotifyAllClass t3 = new NotifyAllClass("t3");
t1.start();
t2.start();
t3.start();
try {
System.out.println(Thread.currentThread().getName() + " sleep 3000 ms");
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj) {
System.out.println(Thread.currentThread().getName() + " 唤醒所有线程");
obj.notifyAll();
}
}
static class NotifyAllClass extends Thread{
public NotifyAllClass(String name) {
super(name);
}
@Override
public void run() {
synchronized (obj) {
try {
System.out.println(Thread.currentThread().getName() + " 执行 wait ");
obj.wait();
System.out.println(Thread.currentThread().getName() + "继续 执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
控制台:
main sleep 3000 ms
t1 执行 wait
t3 执行 wait
t2 执行 wait
main 唤醒所有线程
t2继续 执行
t3继续 执行
t1继续 执行
t1,t2,t3和主线程 分别执行, t1,t2,t3线程分别 持有ojb对象,并执行了等待,并释放各自的锁,都进入阻塞状态,主线程(mian)线程 sleep 之后,获取obj对象的锁,执行notifyAll,唤醒所有线程.t1,t2,t3之后并执行结束,释放obj的同步锁,之后被唤醒并继续执行.
最后: notify() 和 wait() 等方法依赖于 同步锁 ,同步锁依赖于 对象,所以,这些方法也是依赖于 对象 的.
yield() demo
package cn.kkcoder.thread;
public class YieldTet {
static Object obj = new Object();
public static void main(String[] args) {
TestYield t1 = new TestYield("t1");
TestYield t2 = new TestYield("t2");
t1.start();
t2.start();
}
static class TestYield extends Thread{
public TestYield(String name) {
super(name);
}
@Override
public void run() {
synchronized(obj) {
for(int i=0;i<=5;i++) {
System.out.println(Thread.currentThread().getName() + " i = " + i);
if(i%3==0) {
System.out.println(Thread.currentThread().getName() + " 执行yield");
Thread.yield();
}
}
}
}
}
}
控制台:
t1 i = 0
t1 执行yield
t1 i = 1
t1 i = 2
t1 i = 3
t1 执行yield
t1 i = 4
t1 i = 5
t2 i = 0
t2 执行yield
t2 i = 1
t2 i = 2
t2 i = 3
t2 执行yield
t2 i = 4
t2 i = 5
yield() 方法会进行让步,但不会释放同步锁.即yield会把该线程从运行状态,转换到 就绪状态.