18.4 操作線程的方法
一、線程的休眠
一種控制線程行為的方法使調用sleep()方法,sleep()方法需要一個參數用於指定該線程休眠的時間,該時間以毫秒為單位
sleep()方法的語法如下:
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
上述代碼會使線程在2秒之內不會進入就緒狀態。由於sleep()方法的執行有可能拋出InterruptedException異常,所以將sleep()方法的調用放在try-catch塊中。雖然使用sleep()方法的線程在一段時間內會醒來,但是並不能保證它醒來後進入運行狀態,只能保證它進入就緒狀態。
1 package com.lzw; 2 3 import java.awt.*; 4 import java.util.*; 5 6 import javax.swing.*; 7 public class SleepMethodTest extends JFrame { 8 /** 9 * 10 */ 11 private static final long serialVersionUID = 1L; 12 private Thread t; 13 // 定義顏色數組 14 private static Color[] color = { Color.BLACK, Color.BLUE, Color.CYAN,View Code15 Color.GREEN, Color.ORANGE, Color.YELLOW, Color.RED, 16 Color.PINK, Color.LIGHT_GRAY }; 17 private static final Random rand = new Random();// 創建隨機對象 18 19 private static Color getC() {// 獲取隨機顏色值的方法 20 return color[rand.nextInt(color.length)]; 21 } 22 23public SleepMethodTest() { 24 t = new Thread(new Runnable() {// 創建匿名線程對象 25 int x = 30;// 定義初始坐標 26 int y = 50; 27 28 public void run() {// 覆蓋線程接口方法 29 while (true) {// 無限循環 30 try { 31 Thread.sleep(100);// 線程休眠0.1秒 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 // 獲取組件繪圖上下文對象 36 Graphics graphics = getGraphics(); 37 graphics.setColor(getC());// 設置繪圖顏色 38 // 繪制直線並遞增垂直坐標 39 graphics.drawLine(x, y, 100, y++); 40 if (y >= 80) { 41 y = 50; 42 } 43 } 44 } 45 }); 46 t.start();// 啟動線程/ 47 } 48 49 public static void main(String[] args) { 50 init(new SleepMethodTest(), 100, 100); 51 } 52 // 初始化程序界面的方法 53 public static void init(JFrame frame, int width, int height) { 54 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 55 frame.setSize(width, height); 56 frame.setVisible(true); 57 } 58 }
二、線程的加入
如果當前某程序為多線程序,加入存在一個線程A,現在需要插入線程B,並要求線程B先執行完畢,然後再繼續執行線程A,此時可以使用Thread類中的join()方法來完成。
當某個線程使用join()方法加入到另一個線程時,另一個線程會等待該線程執行完畢後再繼續執行。
1 package com.lzw; 2 3 import java.awt.*; 4 import javax.swing.*; 5 6 public class JoinTest extends JFrame { 7 /** 8 * 9 */ 10 private static final long serialVersionUID = 1L; 11 private Thread threadA; // 定義兩個線程 12 private Thread threadB; 13 final JProgressBar progressBar = new JProgressBar(); // 定義兩個進度條組件 14 final JProgressBar progressBar2 = new JProgressBar(); 15 int count = 0; 16 17 public static void main(String[] args) { 18 init(new JoinTest(), 100, 100); 19 } 20 21 public JoinTest() { 22 super(); 23 // 將進度條設置在窗體最北面 24 getContentPane().add(progressBar, BorderLayout.NORTH); 25 // 將進度條設置在窗體最南面 26 getContentPane().add(progressBar2, BorderLayout.SOUTH); 27 progressBar.setStringPainted(true); // 設置進度條顯示數字字符 28 progressBar2.setStringPainted(true); 29 // 使用匿名內部類形式初始化Thread實例子 30 threadA = new Thread(new Runnable() { 31 int count = 0; 32 33 public void run() { // 重寫run()方法 34 while (true) { 35 progressBar.setValue(++count); // 設置進度條的當前值 36 try { 37 Thread.sleep(100); // 使線程A休眠100毫秒 38 threadB.join(); // 使線程B調用join()方法 39 } catch (Exception e) { 40 e.printStackTrace(); 41 } 42 } 43 } 44 }); 45 threadA.start(); // 啟動線程A 46 threadB = new Thread(new Runnable() { 47 int count = 0; 48 49 public void run() { 50 while (true) { 51 progressBar2.setValue(++count); // 設置進度條的當前值 52 try { 53 Thread.sleep(100); // 使線程B休眠100毫秒 54 } catch (Exception e) { 55 e.printStackTrace(); 56 } 57 if (count == 100) // 當count變量增長為100時 58 break; // 跳出循環 59 } 60 } 61 }); 62 threadB.start(); // 啟動線程B 63 } 64 65 // 設置窗體各種屬性方法 66 public static void init(JFrame frame, int width, int height) { 67 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 68 frame.setSize(width, height); 69 frame.setVisible(true); 70 } 71 }View Code
三、線程的中斷
以往有的時候回使用stop()方法停止線程,但當前版本的JDK早已廢除了stop()方法,不建議使用stop()方法來停止一個線程的運行。現在提倡在run()方法中使用無線循環的形式,然後使用一個布爾型標記控制循環的停止。
如果線程因為使用了sleeo()方法或wait()方法進入了就緒狀態,可以使用Thread類中的interrupt()方法時線程離開run()方法,同時結束線程,但程序會拋出InterruptedException異常,用戶可以在處理該異常時完成線程的中斷業務處理,如終止while循環。
1 package com.lzw; 2 3 public class InterruptedTest implements Runnable{ 4 private boolean isContinue = false; //設置一個編輯變量,默認值為false 5 6 public void run() { 7 while(true) { 8 //... 9 if(isContinue) //當isContinue變量為true時,停止線程 10 break; 11 } 12 } 13 14 public void setContinue() { 15 this.isContinue = true; //定義設置isContinue變量為true的方法 16 } 17 }View Code
1 package com.lzw; 2 3 import java.awt.*; 4 import javax.swing.*; 5 6 public class InterruptedSwing extends JFrame { 7 /** 8 * 9 */ 10 private static final long serialVersionUID = 1L; 11 Thread thread; 12 13 public static void main(String[] args) { 14 init(new InterruptedSwing(), 100, 100); 15 } 16 17 public InterruptedSwing() { 18 super(); 19 final JProgressBar progressBar = new JProgressBar(); // 創建進度條 20 // 將進度條放置在窗體合適位置 21 getContentPane().add(progressBar, BorderLayout.NORTH); 22 progressBar.setStringPainted(true); // 設置進度條上顯示數字 23 thread = new Thread(new Runnable() { 24 int count = 0; 25 26 public void run() { 27 while (true) { 28 progressBar.setValue(++count); // 設置進度條的當前值 29 try { 30 Thread.sleep(1000); // 使線程休眠1000豪秒 31 // 捕捉InterruptedException異常 32 } catch (InterruptedException e) { 33 System.out.println("當前線程序被中斷"); 34 break; 35 } 36 } 37 } 38 }); 39 thread.start(); // 啟動線程 40 thread.interrupt(); // 中斷線程 41 } 42 43 public static void init(JFrame frame, int width, int height) { 44 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 45 frame.setSize(width, height); 46 frame.setVisible(true); 47 } 48 49 }View Code
四、線程的禮讓
Thread類中提供了一種禮讓方法,使用yield()方法表示,它只是給當前正處於運行狀態的線程一個提醒,告知它可以將資源禮讓給其它線程,但這僅是一種暗示,沒有任何一種機制保證當前線程會將資源禮讓。
yield()方法使具有同樣優先級的線程有進入可執行狀態的機會,當當前線程放棄執行權時會再度回到就緒狀態。對於支持多任務的操作系統來說,不需要調用yield()方法,因為操作系統會為線程自動分配CPU時間片來執行。
18.4 操作線程的方法