Java 多線程(中)
在 《【重磅出擊】 java入門到精通——多線程(上)》中,詳細講解了線程與進程,建立線程的兩種方法,和線程的生命週期。這裡我們講解一些控制線程的方法。控制線程之join
join方法:調用join方法的線程對象強制運行,該線程強制運行期間,其他線程無法運行,必須等到該線程結束後其他線程才可以運行,有人也把這種方式成為聯合線程。
代碼如下:
public class JoinDemo {public static void main(String[] args) throws Exception {Thread join = new Thread(new Join(),"Join線程");join.start();int i = 0;while(i < 500){if(i == 100){join.join();}System.out.println("Main -- > " + i ++);}}}class Join implements Runnable {public void run() {int i = 0;while(i< 200){System.out.println(Thread.currentThread().getName() + "--" + i ++ );}}}
控制線程之Daemon
後台線程:處於後台運行,任務是為其他線程提供服務。也稱為“守護線程”或“精靈線程”。JVM的記憶體回收就是典型的後台線程。
特點:若所有的前台線程都死亡,後台線程自動死亡。
設定後台線程:Thread對象setDaemon(true);
setDaemon(true)必須在start()調用前,否則出現IllegalThreadStateException異常;
前台線程建立的線程預設是前台線程;判斷是否是後台線程:使用Thread對象的isDaemon()方法;
並且若且唯若建立線程是後台線程時,新線程才是後台線程。
代碼如下:
class Daemon extends Thread {public void run() {for (int i = 0; i < 10000; i++) {System.out.println(getName() + "-" + i);}}}public class DaemonDemo {public static void main(String[] args) {Daemon d = new Daemon();d.setDaemon(true);//把 d 線程設定成後台線程d.start();for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName()+"--" + i);}}}
控制線程之sleep
線程休眠:
讓執行的線程暫停一段時間,進入阻塞狀態,注意此方法會拋出異常。
sleep(long milllis) throws InterruptedException:毫秒
調用sleep()後,在指定時間段之內,該線程不會獲得執行的機會。
代碼如下:
public class SleepDemo {public static void main(String[] args) {for (int i = 10; i > 0; i--) {System.out.println("還剩" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}
控制線程之優先順序
每個線程都有優先順序,優先順序的高低只和線程獲得執行機會的次數多少有關。並非線程優先順序越高的就一定先執行,哪個線程的先運行取決於CPU的調度; 預設情況下main線程具有普通的優先順序,而它建立的線程也具有普通優先順序。
Thread對象的setPriority(int x)和getPriority()來設定和獲得優先順序。
MAX_PRIORITY : 值是10
MIN_PRIORITY : 值是1
NORM_PRIORITY : 值是5(主方法預設優先順序)
代碼如下:
class Priority extends Thread{public void run() {for (int i = 0; i < 100; i++) {System.out.println(getName()+",優先順序=" + getPriority() +"--"+ i);}}}public class PriorityDemo {public static void main(String[] args) {Thread.currentThread().setPriority(7);for (int i = 0; i < 100; i++) {if(i == 10){Priority p1 = new Priority();p1.setPriority(Thread.MAX_PRIORITY);p1.start();}if(i == 15){Priority p2 = new Priority();p2.setPriority(Thread.MIN_PRIORITY);p2.start();}System.out.println("main" + i);}}}
控制線程之yield
線程禮讓:
暫停當前正在執行的線程對象,並執行其他線程;
Thread的靜態方法,可以是當前線程暫停,但是不會阻塞該線程,而是進入就緒狀態。所以完全有可能:某個線程調用了yield()之後,線程調度器又把他調度出來重新執行。
代碼如下:
class Yield implements Runnable {public void run() {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName() + "--> " + i);if (i % 2 == 0) {Thread.yield();// 禮讓}}}}public class YieldDemo {public static void main(String[] args) {Yield y = new Yield();new Thread(y, "A").start();new Thread(y, "C").start();}}
控制線程之結束線程
我們使用一個boolean型變數來控制線程的結束。
boolean flag = true;//用變數來控制線程public void run() {int i = 0;while (flag) {if (i == 25) {flag = false;}System.out.println("==" + i);i++;}}
API過時方法--易死結,不推薦使用
stop:終止線程
馬上讓線程停止運行,並釋放該線程所持有的鎖,該操作無法保證對象的內部狀態正確;
suspend:掛起線程
使線程進入“阻塞”狀態,該狀態下CPU不會分給線程時間片,進入這個狀態可以用來暫停一個線程的運行,在被resume方法調用前,不可用.
如果要suspend的目標線程對一個重要的系統資源持有鎖,那麼沒任何線程可以使用這個資源直到要suspend的目標線程被resumed。
resume:恢複線程
恢複被suspend方法掛起的線程