注意一种特殊情况:线程调用wait方法进入冻结状态(中断状态)时,不会读取到标记,如果没有唤醒,那就会一直等待,结束不了。这时候,可以使用interrupt方法,是程序中断,这个方法会抛出InterruptedException异常,可以把在catch块里改变线程标记,使线程结束。

一,停止线程

package fighting;
public class ThreadStopDemo {
 /**
  * 一,停止线程:
  * stop方法,已过时。
  * 如何停止线程?停止线程的原理:
  * 只有一种:run方法结束。线程要执行的代码执行完了就会结束。
  * 
  * 开启多线程运行,运行代码通常都是循环结构。
  * 只要控制住循环,就可以让run方法结束,也就是线程结束。
  * 
  * 当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。
  * 强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。
  * Thread类提供该方法interrupt();
  */
 public static void main(String[] args) {
  
  StopThread st= new StopThread();
  
  Thread t1 = new Thread(st);
  Thread t2 = new Thread(st);
  
  t1.start();
  t2.start();
  
  int num = 0;
  while(true){
   if(num++==30){
//    st.changeFlag();//主线程中num==60,flag置为false,run方法结束
    t1.interrupt();
    t2.interrupt();
    break;
   }
   System.out.println(Thread.currentThread().getName()+"...main:"+num);
  }
  System.out.println("over");
 }
}
class StopThread implements Runnable{
 private boolean flag = true;
/* public void run() {//这种情况,程序是正常的
  while(flag){
   System.out.println(Thread.currentThread().getName()+"...run");
  }
  
 }*/
 public synchronized void run(){//这种情况,就会出现主线程循环30次结束,t1、t2线程仍未结束的情况。
  while(flag){
   System.out.println(Thread.currentThread().getName()+"...starting");
   try{
    wait();//t1,t2一进来都停在了这里。主线程结束也不会停止。
           //这是一种特殊情况,当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。
           //遇到这种情况,我们可以使用interrupt方法强制使冻结状态的线程结束。
   }catch(InterruptedException e){
    System.out.println(Thread.currentThread().getName()+"...InterruptedException");
    flag=false;
   }
   System.out.println(Thread.currentThread().getName()+"...running");
  }
  System.out.println(Thread.currentThread().getName()+"over");
 }
 public void changeFlag(){
  flag=false;
 }
 
}

运行结果:

Thread-0...starting
 main...main:1
 Thread-1...starting
 main...main:2
 main...main:3
 main...main:4
 main...main:5
 main...main:6
 main...main:7
 main...main:8
 main...main:9
 main...main:10
 main...main:11
 main...main:12
 main...main:13
 main...main:14
 main...main:15
 main...main:16
 main...main:17
 main...main:18
 main...main:19
 main...main:20
 main...main:21
 main...main:22
 main...main:23
 main...main:24
 main...main:25
 main...main:26
 main...main:27
 main...main:28
 main...main:29
 main...main:30
 over
 Thread-1...InterruptedException
 Thread-1...running
 Thread-1over
 Thread-0...InterruptedException
 Thread-0...running
 Thread-0over

 二,守护线程:

package fighting;
public class ThreadStopDemo {
 /**

  * 二,守护线程:
  * 另外还有一种解决上面这种情况的方法:利用setDaemon(boolean on)方法,这个方法将线程标记为守护线程或用户线程,类似于后台线程。
  * 当正在运行的线程都是守护线程时,Java 虚拟机退出。利用这一特点,把本程序中的t1、t2设置为守护线程,
  * 那么当主线程结束,t1、t2就会自动结束,即使二者处于运行状态也会自动结束。
  * 注意该方法必须在启动线程前调用。
  * 当前台线程结束,后台线程自动结束。
  */
 public static void main(String[] args) {
  
  StopThread st= new StopThread();
  
  Thread t1 = new Thread(st);
  Thread t2 = new Thread(st);
  //将t1、t2设为守护线程
  t1.setDaemon(true);
  t2.setDaemon(true);
  
  t1.start();
  t2.start();
  
  int num = 0;
  while(true){
   if(num++==30){
//    st.changeFlag();//主线程中num==60,flag置为false,run方法结束
//    t1.interrupt();
//    t2.interrupt();
    break;
   }
   System.out.println(Thread.currentThread().getName()+"...main:"+num);
  }
  System.out.println("over");
 }
}
class StopThread implements Runnable{
 private boolean flag = true;
/* public void run() {
  while(flag){
   System.out.println(Thread.currentThread().getName()+"...run");
  }
  
 }*/
 public synchronized void run(){
  while(flag){
   System.out.println(Thread.currentThread().getName()+"...starting");
   try{
    wait();//t1,t2一进来都停在了这里。主线程结束也不会停止。
           //这是一种特殊情况,当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。
           //遇到这种情况,我们可以使用interrupt方法强制使冻结状态的线程进入运行状态。
   }catch(InterruptedException e){
    System.out.println(Thread.currentThread().getName()+"...InterruptedException");
//    flag=false;
   }
   System.out.println(Thread.currentThread().getName()+"...running");
  }
  System.out.println(Thread.currentThread().getName()+"over");
 }
 public void changeFlag(){
  flag=false;
 }
 
}

运行结果:

Thread-0...starting
 main...main:1
 Thread-1...starting
 main...main:2
 main...main:3
 main...main:4
 main...main:5
 main...main:6
 main...main:7
 main...main:8
 main...main:9
 main...main:10
 main...main:11
 main...main:12
 main...main:13
 main...main:14
 main...main:15
 main...main:16
 main...main:17
 main...main:18
 main...main:19
 main...main:20
 main...main:21
 main...main:22
 main...main:23
 main...main:24
 main...main:25
 main...main:26
 main...main:27
 main...main:28
 main...main:29
 main...main:30
 over