(欢迎关注微信公众号:深入Java底层)
1、停止线程
1.1 停止不了的线程
调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。
1.2 判断线程是否是停止状态
this.interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能。
package t12;
publicclass MyThread extends Thread {
@Override
publicvoid run() {
super.run();
for(int i=0;i<500000;i++){
System.out.println("i="+ (i+1));
}
}
}
package t12;
publicclass Run2 {
/**
* @param args
*/
publicstaticvoidmain(String[] args) {
//thread.interrupt();
Thread.currentThread().interrupt();
System.out.println("是否停止1? =" + Thread.interrupted());
System.out.println("是否停止2? =" + Thread.interrupted());
System.out.println("end!");
}
}
运行结果:
//thread.interrupt();
是否停止1? =false
是否停止2? =false
end!
// Thread.currentThread().interrupt();
是否停止1? =true
是否停止2? =false
end!
this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志。
package t12;
publicclass Run3 {
/**
* @param args
*/
publicstaticvoidmain(String[] args) {
try {
MyThreadthread = new MyThread();
thread.start();
Thread.sleep(1000);
thread.interrupt();
//Thread.currentThread().interrupt();
System.out.println(" 是否停止1? =" +thread.isInterrupted());
System.out.println(" 是否停止2? =" +thread.isInterrupted());
} catch(InterruptedException e) {
System.out.println("maincatch");
e.printStackTrace();
}
System.out.println("end!");
}
}
运行结果:
//thread.interrupt();
是否停止1? =true
是否停止2? = true
end!
1.3 异常法停止的线程
在线程中用for语句来判断一下线程是否停止状态,如果是停止状态,则后面的代码不再运行即可。但如果for语句下面还有语句,还是会继续运行。使用“抛异常”的方法可以解决上面的问题,参看如下代码。
package t13_1;
publicclass Run {
publicstaticvoidmain(String[] args) {
try {
MyThreadthread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
} catch(InterruptedException e) {
System.out.println("maincatch");
e.printStackTrace();
}
System.out.println("end!");
}
}
package t13_1;
publicclass Run {
publicstaticvoidmain(String[] args) {
try {
MyThreadthread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
} catch(InterruptedException e) {
System.out.println("maincatch");
e.printStackTrace();
}
System.out.println("end!");
}
/**
* 运行结果:
* ...
i=352988
i=352989
i=352990
i=352991
i=352992
i=352993
已经停止状态了,我要退出了
end!
进MyThread.java类run方法中的catch了!
java.lang.InterruptedException
att13_1.MyThread.run(MyThread.java:11)
*
*/
}
1.4 在沉睡中停止
如果在sleep状态下停止某一线程,会进入catch语句,并且清除停止状态值,使之变成false;
package t14;
publicclass MyThread extends Thread {
@Override
publicvoid run() {
super.run();
try{
System.out.println("runbegin");
Thread.sleep(200000);
System.out.println("runend");
}catch(InterruptedExceptione){
System.out.println("在沉睡中被停止!进入catch!" + Thread.interrupted());
e.printStackTrace();
}
}
}
package t14;
publicclass Run {
/**
* @param args
*/
publicstaticvoidmain(String[] args) {
try {
MyThreadthread = new MyThread();
thread.start();
Thread.sleep(200);
thread.interrupt();
} catch(InterruptedException e) {
System.out.println("maincatch");
e.printStackTrace();
}
System.out.println("end!");
}
/**
* 运行结果:
* run begin
end!
在沉睡中被停止!进入catch!false
java.lang.InterruptedException: sleepinterrupted
at java.lang.Thread.sleep(Native Method)
at t14.MyThread.run(MyThread.java:10)
*
*/
}
如果先interrupt()然后再sleep,也会进入catch语句,并且清除停止状态值,使之变成false。
package t15;
publicclass MyThread extends Thread {
@Override
publicvoid run() {
super.run();
try{
for(inti=0;i<100000;i++){
System.out.println("i="+(i+1));
}
System.out.println("runbegin");
Thread.sleep(200000);
System.out.println("runend");
}catch(InterruptedExceptione){
System.out.println("先停止!再遇到了sleep!进入catch!"+ Thread.interrupted());
e.printStackTrace();
}
}
/**
* 先interrupt()然后再sleep,也会进入catch语句,并且清除停止状态值。
*
*/
}
package t15;
publicclass Run {
/**
* @param args
*/
publicstaticvoidmain(String[] args) {
MyThreadthread = new MyThread();
thread.start();
thread.interrupt();
System.out.println("end!");
}
/**
* 运行结果:
* …………….
* i=99995
i=99996
i=99997
i=99998
i=99999
i=100000
runbegin
先停止!再遇到了sleep!进入catch!false
java.lang.InterruptedException:sleep interrupted
atjava.lang.Thread.sleep(Native Method)
att15.MyThread.run(MyThread.java:13)
*
*/
}
1.5 使用return停止线程
将方法interrupt()与return结合使用也能实现停止线程的效果。不过还是建议使用“抛异常”的方法来实现线程的停止,因为在catch块中还可以将异常向上抛,使线程停止的事件得以传播。
2. yield方法
yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
3. 线程的优先级
在操作系统中,线程可以划分优先级,优先级较高的线程得到
的CPU资源较多,也就是CPU优先执行优先级较高的线程对象中任务。
在Java中,线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A是一样的。如果A线程的优先级被更改,B线程将继承更改。
package t18;
publicclass MyThread1 extends Thread {
@Override
publicvoid run() {
System.out.println("MyThread1run priority=" + this.getPriority());
MyThread2thread2 = new MyThread2();
thread2.start();
}
}
package t18;
publicclass MyThread2 extends Thread {
@Override
publicvoid run() {
System.out.println("MyThread2run priority=" + this.getPriority());
}
}
package t18;
publicclass Run {
/**
* @param args
*/
publicstaticvoidmain(String[] args) {
System.out.println("mainthread begin priority=" + Thread.currentThread().getPriority());
// Thread.currentThread().setPriority(6);
System.out.println("mainthread begin priority=" + Thread.currentThread().getPriority());
MyThread1thread1 = new MyThread1();
thread1.start();
}
/**
* 运行结果:
* main thread begin priority=5
mainthread begin priority=5
MyThread1run priority=5
MyThread2run priority=5
*
* 去掉注释,运行结果:
* main thread begin priority=5
mainthread begin priority=6
MyThread1run priority=6
MyThread2run priority=6
*
*
* 在java中,线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A是一样的。
*/
}
线程的优先级具有一定的规则性,也就是CPU尽量将执行资源让给优先级比较高的线程,但优先级较高的线程并不一定每一次都先执行完,线程的优先级还具有“随机性”。优先级高的运行得快,但是测试的时候好多次并没有更快。
4. 守护线程
在Java线程中两种线程,一种是用户线程,另一种是守护线程。
守护线程是一种特殊的线程,当线程中不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程,当进程中没有非守护线程了,则垃圾回收线程也就没有存在的必要了,自动销毁。Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是GC(垃圾回收器),它就是一个很称职的守护者。
(欢迎关注微信公众号:深入Java底层)