Java提供了3个非常重要的方法来巧妙地解决线程间的通信问题。这3个方法分别是:wait()、notify()和notifyAll()。它们都是Object类的最终方法,因此每一个类都默认拥有它们。
尽管在主方法中先启动了Consumer线程,但是,由于仓库中没有产品,因此,Consumer线程就会调用wait()方法进入等待队列进行等待,直到Producer线程将产品生产出来并放进仓库,然后使用notify()方法将其唤醒。
如何结束线程:
三种方式
1.使用flag标志位。 怎么结束run方法呢? 控制run方法当中的循环就可以了。 怎么控制循环呢? 在循环当中设置标志位,通过标志位来完成。 setFlag(false)
class StopRun implements Runnable{
private boolean flag = true;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
while (flag) {
System.out.println(Thread.currentThread().getName()+".....run");
}
}
}
public class StopThreadDemo01 {
public static void main(String[] args) {
StopRun sRun = new StopRun();
Thread t1 = new Thread(sRun);
Thread t2 = new Thread(sRun);
t1.start();
t2.start();
int num = 0;
while (true) {
if (++num==50) {
sRun.setFlag(false);
break;
}
System.out.println(Thread.currentThread().getName()+".....run.."+num);
}
System.out.println("over");
}
}
针对没有阻塞的情况:设置标志变量,让线程正常自然死亡,和谐!
针对有阻塞的情况:中断阻塞,靠抛出异常终止线程
2.interrupt方法
(1)如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法,或者该类的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,则其中断状态将被清除,它还将收到一个InterruptedException异常。这个时候,我们可以通过捕获InterruptedException异常来终止线程的执行,具体可以通过return等退出或改变共享变量的值使其退出。
(2)如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。这时候处理方法一样,只是捕获的异常不一样而已。
如果在中断时,线程正处于非阻塞状态,则将中断标志修改为true,而在此基础上,一旦进入阻塞状态,则按照阻塞状态的情况来进行处理;例如,一个线程在运行状态中,其中断标志被设置为true,则此后,一旦线程调用了wait、jion、sleep方法中的一种,立马抛出一个InterruptedException,且中断标志被清除,重新设置为false。
通过上面的分析,我们可以总结,调用线程类的interrupted方法,其本质只是设置该线程的中断标志,将中断标志设置为true,并根据线程状态决定是否抛出异常。因此,通过interrupted方法真正实现线程的中断原理是:开发人员根据中断标志的具体值,来决定如何退出线程。
public void run() {
try {
while (true){
Thread.sleep(1000l);//阻塞状态,线程被调用了interrupte()方法,清除中断标志,抛出InterruptedException
//dosomething
boolean isIn = this.isInterrupted();
//运行状态,线程被调用了interrupte()方法,中断标志被设置为true
//非阻塞状态中进行中断线程操作
if(isInterrupted()) break;//退出循环,中断进程
}
}catch (InterruptedException e){//阻塞状态中进行中断线程操作
boolean isIn = this.isInterrupted();//退出阻塞状态,且中断标志被清除,重新设置为false,所以此处的isIn为false
return;//退出run方法,中断进程
}
}
3.强行制造一个异常