wait()方法
其实wait()方法就是使线程停止运行。
1.方法wait()的作用是使当前执行代码的线程进行等待,它是Object类的方法,该方法是用来将当前线程置入“预执行队列”当中,并且在wait() 所处代码处停止执行,直到接到通知或被中断为止。
2.wait()方法只能在同步方法中或同步块中调用。如果调用wait()时,没有持有适当的锁,会抛出异常。
3.wait()方法执行后当前线程释放锁,线程与其他线程竞争重新获取锁
public class Line{
public static void main(String[] args) throws InterruptedException {
Object object=new Object();
synchronized (object) {
System.out.println("线程等待中,,,,,,,,,");
object.wait();
}
System.out.println("线程等待结束");
}
}
结果:
线程等待中,,,,,,,,,
程序就在一直等待着,直到用另一个方法唤醒notify()。
notify()方法
notify方法就是使停止的线程继续执行。
1.它也要在同步方法或同步代码块中调用,该方法是用来通知那些可能等待该对象的对象锁的其他线程,对其发出通知notify,并使它们重新获取该对象的对象锁。如果有多个线程等待,则有线程规划器随机挑选出一个呈wait状态的线程。
2.在notify()方法后,当前线程不会马上释放对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。
class MyThread implements Runnable{
private boolean flag;
private Object obj;
public MyThread(boolean flag, Object obj) {
super();
this.flag = flag;
this.obj = obj;
}
public void waitMethod() {
synchronized (obj) {
try {
while(true) {
System.out.println("wait()方法开始。。"+Thread.currentThread().getName());
obj.wait();
System.out.println("wait()方法结束。。"+Thread.currentThread().getName());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void notifyMethod() {
synchronized (obj) {
try {
System.out.println("notify()方法开始。。"+Thread.currentThread().getName());
obj.notify();
System.out.println("notify()方法结束。。"+Thread.currentThread().getName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void run() {
if(flag) {
this.waitMethod();
}else {
this.notifyMethod();
}
}
}
public class Line{
public static void main(String[] args) throws InterruptedException {
Object object=new Object();
MyThread waitThread=new MyThread(true,object);
MyThread notifyThread=new MyThread(false,object);
Thread thread1=new Thread(waitThread,"wait线程");
Thread thread2=new Thread(notifyThread,"notify线程");
thread1.start();
Thread.sleep(1000);
thread2.start();
System.out.println("main方法结束");
}
}
结果:
wait()方法开始。。wait线程
main方法结束
notify()方法开始。。notify线程
notify()方法结束。。notify线程
wait()方法结束。。wait线程
wait()方法开始。。wait线程
notifyAl()方法
可以一次性唤醒所有等待线程。
class MyThread implements Runnable{
private boolean flag;
private Object obj;
public MyThread(boolean flag, Object obj) {
super();
this.flag = flag;
this.obj = obj;
}
public void waitMethod() {
synchronized (obj) {
try {
while(true) {
System.out.println("wait()方法开始。。"+Thread.currentThread().getName());
obj.wait();
System.out.println("wait()方法结束。。"+Thread.currentThread().getName());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void notifyAllMethod() {
synchronized (obj) {
try {
System.out.println("notifyAll()方法开始。。"+Thread.currentThread().getName());
obj.notify();
System.out.println("notifyAll()方法结束。。"+Thread.currentThread().getName());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void run() {
if(flag) {
this.waitMethod();
}else {
this.notifyAllMethod();
}
}
}
public class Line{
public static void main(String[] args) throws InterruptedException {
Object object=new Object();
MyThread waitThread1=new MyThread(true,object);
MyThread waitThread2=new MyThread(true,object);
MyThread waitThread3=new MyThread(true,object);
MyThread notifyAllThread=new MyThread(false,object);
Thread thread1=new Thread(waitThread1,"wait线程1");
Thread thread2=new Thread(waitThread2,"wait线程2");
Thread thread3=new Thread(waitThread3,"wait线程3");
Thread thread4=new Thread(notifyAllThread,"notify线程");
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(1000);
thread4.start();
System.out.println("main方法结束");
}
}
结果:
wait()方法开始。。wait线程1
wait()方法开始。。wait线程3
wait()方法开始。。wait线程2
main方法结束
notifyAll()方法开始。。notify线程
notifyAll()方法结束。。notify线程
wait()方法结束。。wait线程1
wait()方法开始。。wait线程1
注意:唤醒线程不能过早,如果在还没有线程在等待中,过早地唤醒线程,这个时候就会出现先唤醒再等待的效果了。
小结:出现阻塞的情况大体分为如下5种:
1.线程调用sleep方法,主动放弃占用的处理的资源处理器资源。
2.线程调用了阻塞式IO方法,在改方法返回前,该线程被阻塞。
3.线程视图获得一个同步监视器,但是该同步监视器正被其他线程锁持有。
4.线程等待某个通知。
5.程序调用了suspend方法将该线程挂起。此方法容易导致死锁,尽量避免使用该方法。
run()方法运行结束后进入销毁阶段,整个线程执行完毕。
每个所对象都有两个队列,一个是就绪队列,一个是阻塞队列。就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程。一个线程被唤醒后,才会进入就绪队列,等待CPU的跳读;反之,一个线程被wait()后,就会进入阻塞队列,等待下一次被唤醒。