java線程對象有一些經常使用的方法,如:
(1).currentThread():返回代碼段正在被哪個線程調用。
(2).isAlive():判斷當前線程是否處於活動狀態。
(3).getId():返回線程唯一標示。
(4).interrupt():中斷線程。
(5).interrupted():判斷當前線程是否已經中斷。
(6).isInterrupt():判斷線程是否已經中斷。
(7).stop():將線程強制停止。
(8).suspend():暫停線程。
(9).resume():恢復線程執行。
(10).yield():放棄當前的CPU資源,將它讓給其他任務去佔用CPU執行時間。
下面逐一舉例說明各方法作用。
(1).currentThread():返回代碼段正在被哪個線程調用。
public class Run1 {
public static void main(String[] args) {
System.out.println("當前線程名稱:" + Thread.currentThread().getName());
}
}
輸出爲:“當前線程名稱:main”,說明main方法被名爲main的線程調用。public class MyThread1 extends Thread{
public MyThread1(){
System.out.println("構造方法的打印:" + Thread.currentThread().getName());
}
@Override
public void run(){
System.out.println("run方法的打印:" + Thread.currentThread().getName());
}
}
public class Run1 {
public static void main(String[] args) {
MyThread1 thread = new MyThread1();
thread.start();
//thread.run();
}
}
當執行thread.start();方法和thread.run();方法打印結果分別爲:
打印結果不同的原因在於調用start()方法時,啓動了新的線程,run方法是被新線程來執行的,構造方法兩種情況都是被main線程執行,直接調用run方法時,並未啓動新線程,直接通過main線程執行的run方法,所以兩次打印結果不同。
很多時候Thread.currentThread().getName()會與this.getName()方法進行比較,其實比較的是currentThread和this獲取到線程這兩種方式的區別。
a.Thread.currentThread()在兩種實現線程的方式(實現Runnable接口和繼承Thread類)中都可以使用;this方式只能在繼承方式中使用;
b.currentThread()方法返回的是對當前正在執行的線程的引用,this代表的是當前調用它所在函數所屬的對象的引用。
(2).isAlive():判斷當前線程是否處於活動狀態。
public class Run1 {
public static void main(String[] args) {
MyThread2 thread = new MyThread2();
System.out.println("begin = " + thread.isAlive());
thread.start();
System.out.println("end = " + thread.isAlive());
}
}
什麼是活動狀態呢,活動狀態就是線程已經啓動且尚未終止。線程處於正在運行或準備開始運行的狀態,就認爲線程是“存活”的。
其實上面的結果中end後的狀態是不確定的,有可能是true也可能是false,看main線程執行end這行時,thread線程是否已經執行完畢了,這個地方打印的是true是因爲thread線程還未執行完畢。
(3).getId():返回線程唯一標示。
public class Run1 {
public static void main(String[] args) {
MyThread2 thread = new MyThread2();
System.out.println(thread.getName() + " " + thread.getId());
}
}
輸出爲:Thread-0 10
(4).interrupt():中斷線程。
(5).interrupted():判斷當前線程是否已經中斷。
(6).isInterrupt():判斷線程是否已經中斷。
(7).stop():將線程強制停止。
這幾個方法一起說,因爲這三個方法都是跟停止線程或判斷線程中斷狀態相關。java中有三種方法可以終止正在運行的線程:
a.使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止;
b.使用stop方法強行終止線程,但是不推薦使用這個方法,因爲stop和suspend(暫停線程)及resume(恢復線程執行)一樣,都是作廢過期方法,使用它們可能產生不可預料的結果;
c.使用interrupt方法中斷線程。
interrupt():線程的thread.interrupt()方法是中斷線程,將會設置該線程的中斷狀態位,即設置爲true,中斷的結果線程是死亡、還是等待新的任務或是繼續運行至下一步,就取決於這個程序本身。線程會不時地檢測這個中斷標示位,以判斷線程是否應該被中斷(中斷標示值是否爲true)。它並不像stop方法那樣會中斷一個正在運行的線程。如果線程在調用 Object 類的 wait()、wait(long) 或 wait(long, int) 方法,或者該類的 join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法過程中受阻,則其中斷狀態將被清除,它還將收到一個 InterruptedException。也就是說,interrupt()方法並不會真正中斷一個線程,只是會設置線程的中斷狀態爲true,當線程調用wait()、wait(long)這些方法產生阻塞時,會來判斷線程的狀態是否是中斷,如果是,會拋出InterruptedException異常的方式中斷線程。
public class MyThread2 extends Thread{
@Override
public void run(){
super.run();
for (int i = 1; i <= 500000; i++) {
System.out.println("i=" + i);
}
}
}
public class Run1 {
public static void main(String[] args) {
try {
MyThread2 thread = new MyThread2();
thread.start();
Thread.sleep(1000);
thread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
}
interrupted():測試當前線程是否已經中斷,並且具有清除狀態標誌爲false的作用。換句話說,如果連續兩次調用該方法,則第二次調用將返回false(在第一次調用已經清除了其中中斷狀態之後,且第二次調用檢驗中斷狀態前,當前線程再次中斷的情況除外)。
public class Run1 {
public static void main(String[] args) {
try {
MyThread2 thread = new MyThread2();
thread.start();
Thread.sleep(50);
thread.interrupt();
System.out.println("是否停止1? = " + thread.interrupted());
System.out.println("是否停止2? = " + thread.interrupted());
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
樣例中雖然是在thread對象上調用的interrupt()方法來中斷thread對象所代表的線程,在後面使用interrupted()方法來判斷thread對象所代表的線程是否中斷,但從輸出來看,線程並未停止,這也說明了interrupted()方法的解釋:測試當前線程是否已經中斷。這個“當前線程”是main線程,它從未中斷過,所以打印了兩個false。
public class Run1 {
public static void main(String[] args) {
Thread.currentThread().interrupt();
System.out.println("是否停止1? = " + Thread.interrupted());
System.out.println("是否停止2? = " + Thread.interrupted());
System.out.println("end!");
}
}
此時main線程產生了中斷的效果。
isInterrupt():測試線程Thread對象是否已經是中斷狀態,但不清除狀態標誌。
public static void main(String[] args) {
try {
MyThread2 thread = new MyThread2();
thread.start();
Thread.sleep(50);
thread.interrupt();
System.out.println("是否停止1? = " + thread.isInterrupted());
System.out.println("是否停止2? = " + thread.isInterrupted());
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
stop():暴力終止線程。
public class MyThread3 extends Thread{
@Override
public void run(){
super.run();
for (int i = 1; i <= 10000; i++) {
System.out.println("i=" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
try {
MyThread3 thread = new MyThread3();
thread.start();
Thread.sleep(5000);
thread.stop();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
(8).suspend():暫停線程。
(9).resume():恢復線程執行。
public class MyThread4 extends Thread{
private long i = 0;
public long getI() {
return i;
}
public void setI(long i) {
this.i = i;
}
@Override
public void run(){
super.run();
while(true){
i++;
}
}
}
public static void main(String[] args) {
try {
MyThread4 thread = new MyThread4();
thread.start();
Thread.sleep(5000);
thread.suspend();
System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("A= " + System.currentTimeMillis() + " i=" + thread.getI());
thread.resume();
Thread.sleep(5000);
thread.suspend();
System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("B= " + System.currentTimeMillis() + " i=" + thread.getI());
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
suspend()方法和resume()方法是廢棄方法,也不提倡使用,有獨佔和不同步的缺點。如果使用不當,極易造成公共的同步對象的獨佔,使得其他線程無法訪問公共同步對象。
(10).yield():放棄當前的CPU資源,將它讓給其他任務去佔用CPU執行時間。但放棄的時間不確定,有可能剛剛放棄,馬上又獲得CPU的時間片。
public class MyThread5 extends Thread{
@Override
public void run(){
long beginTime = System.currentTimeMillis();
long count = 0;
for (int i = 0; i < 50000000; i++) {
//Thread.yield();
count = count + i;
}
long endTime = System.currentTimeMillis();
System.out.println("計算結果count=" + count + ",用時:" + (endTime-beginTime) + "ms");
}
}
public static void main(String[] args) {
MyThread5 thread = new MyThread5();
thread.start();
}
註釋Thread.yield();這行時執行結果,很快;
不註釋Thread.yield();這行時執行結果,讓出CPU時間片時,相對來說要慢很多。