概要:
學(xué)習(xí)使用Thread.currentThread()
了解中斷線程的方法
了解sleep方法拋出異常
Thread.currentThread()
Thread.currentThread()方法可返回代碼正在被哪個線程調(diào)用的信息。
public class Counter extends Thread {
//構(gòu)造方法在主線程中被執(zhí)行
public Counter() {
print("constructor begin");
print("Thread.currentThread().getName()------"+Thread.currentThread().getName());//main
print("this.getName()-----------"+this.getName());//Thread-0
print("constructor end");
}
@Override
public void run() {
//在子線程中被執(zhí)行
print("run begin");
print("Thread.currentThread().getName()--------"+Thread.currentThread().getName());
print("this.getName()--------"+this.getName());
print("run end");
}
private void print(String msg){
System.out.println(msg);
}
}
public class Run {
public static void main(String[] args){
Counter counter = new Counter();
Thread t = new Thread(counter);
t.setName("new");
t.start();
}
}
/** 執(zhí)行結(jié)果如下:
constructor begin
Thread.currentThread().getName()------main
this.getName()-----------Thread-0
constructor end
run begin
Thread.currentThread().getName()--------new
this.getName()--------Thread-0
run end
*/
如上,Counter構(gòu)造方法是在main線程中執(zhí)行。run()方法是在new線程中執(zhí)行的。
this.getName()中this指代的是Counter實例,Counter繼承Thread,在初始化會設(shè)置名稱為Thread-0。
第二個線程t初始化,名稱默認(rèn)為Thread-1,后續(xù)重新賦值為new。
停止線程
有三種方法可以使終止線程。
1. 使用退出標(biāo)志,使線程正常退出,也就是當(dāng)run方法完成后線程終止。
2. 使用stop方法強行終止線程(這個方法不推薦使用,因為stop和suspend、resume一樣,也可能發(fā)生不可預(yù)料的結(jié)果)。
3. 使用interrupt方法中斷線程。
interrupt()方法僅僅是在當(dāng)前線程中打了一個停止的標(biāo)記,并不是真的停止線程
換句話說,調(diào)用該方法的線程會被設(shè)置一個“中斷”狀態(tài),用于判斷的中斷狀態(tài)的方法如果返回true說明中斷狀態(tài)被設(shè)置了。
如何判斷線程的狀態(tài)是不是停止的?Thread.java類里提供了兩種方法:
1)this.interrupted(): 測試當(dāng)前線程是否已經(jīng)是中斷狀態(tài),執(zhí)行后具有將狀態(tài)標(biāo)志置為false的功能。如果這個方法被連續(xù)調(diào)用兩次,第二次調(diào)用將返回false。
2)this.isInterrupted(): 測試線程Thread對象是否已經(jīng)是中斷狀態(tài),但不清除狀態(tài)標(biāo)識。
第一種方法,判斷當(dāng)前線程的狀態(tài);第二個方法,判斷調(diào)用者的中斷狀態(tài)。
源碼:
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* Tests if some Thread has been interrupted. The interrupted state
* is reset or not based on the value of ClearInterrupted that is
* passed.
*/
private native boolean isInterrupted(boolean ClearInterrupted);
從源碼中可以看出,最終調(diào)用的是isInterrupted(boolean ClearInterrupted)方法,參數(shù)ClearInterrupted可以控制中斷狀態(tài)清除。
驗證1:
如下代碼雖然調(diào)用了interrupted()方法,但是從運行結(jié)果來看,線程并未停止。
class MyThread extends Thread{
@Override
public void run() {
for(int i =0;i<1000;i++){
System.out.println("number"+i);
}
}
}
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
t.start();
//主線程運行10毫秒之后,中斷子線程t。但是并沒有效果。僅僅是打了一個標(biāo)記
Thread.sleep(10);
t.interrupt();
}
}
驗證2:
從運行結(jié)果可以看出,t.interrupted()返回的是當(dāng)前線程的狀態(tài),即main線程,main從未調(diào)用過interrupt()方法,未被標(biāo)記過狀態(tài),因此返回的結(jié)果都是false。
t.isInterrupted()返回的是t線程的中斷狀態(tài)。主線程運行10毫秒之后,調(diào)用中斷方法,此時返回狀態(tài)為true,表示t.interrupt()方法生效了。
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread t = new MyThread();
t.start();
//主線程運行10毫秒之后,中斷子線程t。
Thread.sleep(10);
t.interrupt();
System.out.println("當(dāng)前線程0:"+t.interrupted());
System.out.println("停止線程1:"+t.isInterrupted());
Thread.sleep(1000);
System.out.println("當(dāng)前線程0:"+t.interrupted());
System.out.println("停止線程1:"+t.isInterrupted());
}
}
/**
當(dāng)前線程0:false
停止線程1:true
當(dāng)前線程0:false
停止線程1:false
*/
驗證3:
連續(xù)兩次調(diào)用interrupted()方法,第二次調(diào)用將返回false
public class Run {
public static void main(String[] args) throws InterruptedException {
Thread.currentThread().interrupt();
System.out.println("停止線程:"+Thread.currentThread().interrupted());
System.out.println("停止線程:"+Thread.currentThread().interrupted());
}
}
/**
停止線程:true
停止線程:false
*/
應(yīng)用
將interrupt()方法和isInterrupted()方法結(jié)合使用,來停止線程。
1.使用break停止線程
public class Counter0 extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 100000; i++) {
if(this.isInterrupted()){
System.out.println("已經(jīng)標(biāo)記了停止?fàn)顟B(tài),我要退出");
break;
}
System.out.println("number"+i);
}
System.out.println("退出for循環(huán),后面依然執(zhí)行");
}
public class Run {
public static void main(String[] args){
try {
Counter0 counter0 = new Counter0();
counter0.start();
Thread.sleep(10);
counter0.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
number776
number777
number778
number779
number780
已經(jīng)標(biāo)記了停止?fàn)顟B(tài),我要退出
退出for循環(huán),后面依然執(zhí)行
*/
使用break的方式并未完全退出子線程,for循環(huán)之外的代碼仍然在執(zhí)行
改進(jìn):
2.使用拋異常的方式,停止線程執(zhí)行
public class Counter0 extends Thread {
@Override
public void run() {
try{
for (int i = 0; i < 100000; i++) {
if(this.isInterrupted()){
System.out.println("已經(jīng)標(biāo)記了停止?fàn)顟B(tài),我要退出");
throw new InterruptedException();
}
System.out.println("number"+i);
}
System.out.println("退出for循環(huán),后面依然執(zhí)行");
}catch (InterruptedException e){
System.out.println("捕獲異常");
}
}
}
/**
number983
number984
number985
已經(jīng)標(biāo)記了停止?fàn)顟B(tài),我要退出
捕獲異常
*/
在沉睡中停止線程
public class Thread implements Runnable{
/**
* Causes the currently executing thread to sleep (temporarily cease
* execution) for the specified number of milliseconds, subject to
* the precision and accuracy of system timers and schedulers. The thread
* does not lose ownership of any monitors.
*
* @param millis
* the length of time to sleep in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public static native void sleep(long millis) throws InterruptedException;
}
InterruptedException當(dāng)前線程睡眠中,如果有任何線程中斷了當(dāng)前線程,拋出異常。當(dāng)拋出異常時,當(dāng)前線程的中斷狀態(tài)被清除,值為false
舉個栗子:
public class Counter0 extends Thread {
@Override
public void run() {
super.run();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("狀態(tài)標(biāo)記:"+this.isInterrupted());
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args){
try {
Counter0 counter0 = new Counter0();
counter0.start();
Thread.sleep(10);
counter0.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
狀態(tài)標(biāo)記:false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.yolo.thread.Counter0.run(Counter0.java:37)
*/