注意一种特殊情况:线程调用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