## Java編程那些事兒96——多線程使用示例1
陳躍峰
出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb)
### 12.3 多線程使用示例
多線程技術對于初學者來說,是編程思維的一種跳躍,在實際學習時,一定要熟悉線程的基礎知識,掌握線程的實現方式,然后就是開始大量的進行實踐,從實踐中領悟線程編程的奧妙以及實現的原理。
下面通過幾個常見的例子演示多線程的基本使用。
### 12.3.1 定時炸彈
定時炸彈是在電影中常見的一種裝置,在該部分就使用多線程技術模擬該功能。實現的功能為:在程序啟動以后進行倒計時,當60秒以后程序結束,在程序運行時可以在控制臺輸入quit控制線程(炸彈)的暫停。
在該示例程序中,開啟了一個系統線程(main方法所在的線程),該線程的作用是啟動模擬定時炸彈的線程,并且在控制臺接受用戶的輸入,并判斷輸入的內容是否為quit,如果是則結束模擬定時炸彈的線程,程序結束。
首先來看一下使用繼承Thread類的方式實現多線程時的代碼示例,代碼如下:
package example1;
~~~
import java.io.*;
/**
?* 模擬定時炸彈線程
?*/
public class TestTimeBomb1 {
???????? public static void main(String[] args) {
?????????????????? //創建線程和啟動線程
?????????????????? TimeBombThread tbt = new TimeBombThread();
?????????????????? //接受控制臺輸入
?????????????????? BufferedReader br = new BufferedReader(
?????????????????????????????????????????????? new InputStreamReader(System.in));
?????????????????? String line;
?????????????????? try{
??????????????????????????? while(true){
???????????????????????????????????? System.out.println("輸入quit結束線程:");
???????????????????????????????????? //獲得控制臺輸入
???????????????????????????????????? line = br.readLine();
???????????????????????????????????? //判斷是否是quit
???????????????????????????????????? if(line.equals("quit")){
?????????????????????????????????????????????? tbt.stopThread(); //結束線程
?????????????????????????????????????????????? break; //結束循環
???????????????????????????????????? }
??????????????????????????? }
?????????????????? }catch(Exception e){}
???????? }
}
?????????????????? package example1;
/**
?* 使用繼承Thread類的方式模擬定時炸彈邏輯
?*/
public class TimeBombThread extends Thread {
???????? int n;
???????? boolean isRun;
???????? public TimeBombThread(){
?????????????????? n = 60;
?????????????????? isRun = true;
?????????????????? start();//啟動線程
???????? }
????????
???????? public void run(){
?????????????????? try{
??????????????????????????? while(isRun){
???????????????????????????????????? Thread.sleep(1000); //延遲1秒
???????????????????????????????????? System.out.println("剩余時間:" + n);
???????????????????????????????????? if(n <= 0){
?????????????????????????????????????????????? isRun = false; //結束線程
?????????????????????????????????????????????? System.out.println("炸彈爆炸!");
?????????????????????????????????????????????? break;
???????????????????????????????????? }
???????????????????????????????????? n--; //時間減少1
??????????????????????????? }
?????????????????? }catch(Exception e){}
???????? }
????????
???????? public void stopThread(){
?????????????????? isRun = false;
???????? }
}
~~~
在該示例代碼中,TestTimeBomb1類中包含的是系統線程,在系統線程中啟動模擬定時炸彈的TimeBombThread線程,然后在TestTimeBomb1中接收用戶的控制臺輸入,如果輸入的內容是quit則結束線程,程序結束,否則忽略用戶的輸入,繼續等待用戶輸入。按照前面介紹的IO知識,在接收控制臺輸入時readLine是阻塞方法,也就是該方法在未獲得用戶輸入時會阻塞系統線程的執行,使系統線程進入到等待狀態,等待用戶輸入。而TimeBombThread實現的邏輯是每隔1秒鐘減少一次數值,并輸出剩余時間,當剩余時間為零時,結束TimeBombThread線程。這樣兩個線程就同時工作了,系統線程等待用戶輸入的同時,模擬定時炸彈的線程繼續執行,這樣程序中就包含了兩個同時執行的流程。
在這里需要特別說明的是,如何控制線程的結束?在本程序中,使用的是讓線程自然死亡的方式,在實際控制線程時,當線程的run方法執行結束則線程自然死亡,所以在本程序中通過控制isRun變量使得線程可以自然結束,從而釋放線程占用的資源。
同樣的功能也可以使用Timer和TimerTask組合的方式實現,實現的代碼如下所示:
package example1;
~~~
import java.io.*;
/**
?* 模擬定時炸彈線程
?*/
public class TestTimeBomb2 {
???????? public static void main(String[] args) {
?????????????????? //創建線程和啟動線程
?????????????????? TimeBombTimerTask tbtt = new TimeBombTimerTask();
?????????????????? //接受控制臺輸入
?????????????????? BufferedReader br = new BufferedReader(
?????????????????????????????????????????????? new InputStreamReader(System.in));
?????????????????? String line;
?????????????????? try{
??????????????????????????? while(true){
???????????????????????????????????? System.out.println("輸入quit結束線程:");
???????????????????????????????????? //獲得控制臺輸入
???????????????????????????????????? line = br.readLine();
???????????????????????????????????? //判斷是否是quit
???????????????????????????????????? if(line.equals("quit")){
?????????????????????????????????????????????? tbtt.stopThread(); //結束線程
?????????????????????????????????????????????? break; //結束循環
???????????????????????????????????? }
??????????????????????????? }
?????????????????? }catch(Exception e){}
???????? }
}
~~~
package example1;
~~~
import java.util.*;
/**
?* 使用Timer和TimerTask組合模擬定時炸彈
?*/
public class TimeBombTimerTask extends TimerTask {
???????? int n;
???????? Timer t;
???????? boolean isRun;
???????? public TimeBombTimerTask(){
?????????????????? n = 60;
?????????????????? isRun = true;
?????????????????? t = new Timer();
?????????????????? t.schedule(this, 0); //啟動線程
???????? }
????????
???????? public void run() {
?????????????????? try{
??????????????????????????? while(isRun){
???????????????????????????????????? Thread.sleep(1000); //延遲1秒
???????????????????????????????????? System.out.println("剩余時間:" + n);
???????????????????????????????????? if(n <= 0){
?????????????????????????????????????????????? stopThread(); //結束線程
?????????????????????????????????????????????? System.out.println("炸彈爆炸!");
?????????????????????????????????????????????? break;??????? //結束循環
???????????????????????????????????? }
???????????????????????????????????? n--; //時間減少1
??????????????????????????? }
?????????????????? }catch(Exception e){}
???????? }
????????
???????? public void stopThread(){
?????????????????? isRun = false;
?????????????????? t.cancel();
???????? }
}
~~~
在該示例代碼中,實現的原理和前面的類似,TestTimeBomb2類實現系統線程,功能是啟動模擬定時炸彈的線程,并接收用戶的控制臺輸入。而TimeBombTimerTask類實現模擬定時炸彈的線程,在該類內部包含啟動線程的Timer對象,當構造該類的對象時,不僅完成該類的初始化,而且啟動線程。
在控制Timer啟動的線程結束時,首先結束當前的TimerTask線程,然后再調用Timer對象的cancel方法結束Timer對象的線程,這樣才可以真正停止這種方式啟動的線程。
至于使用實現Runnable方式實現線程的方式,和繼承Thread類的實現幾乎一致,讀者可以根據第一種方式的實現獨自進行實現,這里就不再重復實現了。
?
- 前言
- (1)序言
- (2)程序設計是什么?
- (3)你適合學習程序設計嗎?
- (4)如何學好程序設計?
- (5)程序設計介紹小結
- (6)計算機軟件基本概念
- (7)進制的概念
- (8)計算機內部的數據表達
- (9)網絡編程基礎
- (10)Java語言簡介
- (11)JDK的獲得、安裝和配置
- (12)第一個HelloWorld程序
- (13)Eclipse基本使用
- (14)Eclipse基礎使用進階
- (15)如何學好Java語法
- (16)代碼框架、關鍵字和標識符
- (17)基本數據類型
- (18)變量和常量
- (19)數據類型轉換
- (20)空白、語句結束和注釋
- (21)算術運算符
- (22)比較運算符
- (23)邏輯運算符
- (24)賦值運算符
- (25)位運算符
- (26)移位運算符
- (27)其它運算符
- (28)運算符優先級
- (29)表達式
- (30)流程控制基礎
- (31)if語句語法(1)
- (32)if語句語法(2)
- (33)if語句語法(3)
- (34)switch語句語法
- (35)while語句語法
- (36)do-while語句語法
- (37)for語句語法
- (38)break和continue語句
- (39)流程控制綜合示例1
- (40)流程控制綜合示例2
- (41)流程控制綜合示例3
- (42)流程控制綜合練習
- (43)數組概述
- (44)數組基礎語法
- (45)數組使用示例1
- (46)數組使用示例2
- (47)數組使用示例3
- (48)多維數組基礎
- (49)多維數組使用示例1
- (50)多維數組使用示例2
- (51)多維數組練習
- (52)方法聲明
- (53)方法聲明示例
- (54)方法調用
- (55)方法重載和參數傳遞
- (56)方法練習
- (57)面向對象基礎
- (58)類(一)
- (59)類(二)
- (60)對象
- (61)面向對象設計方法和面向對象特性(一)
- (62)繼承(二)
- (63)多態性
- (64)訪問控制符、修飾符和其它關鍵字
- (65)static修飾符
- (66)final修飾符
- (67)this和super
- (68)抽象類和接口(一)
- (69)抽象類和接口(二)
- (70)抽象類和接口(三)
- (71)內部類簡介
- (72)包的概念
- (73)JDK文檔使用
- (74)java.lang包介紹1
- (75)String類使用
- (76)StringBuffer類和System類
- (77)包裝類
- (78)時間和日期處理
- (79)Random隨機處理
- (80)集合框架簡述
- (81)異常處理概述
- (82)異常處理語法1
- (83)異常處理語法2
- (84)IO簡介
- (85)IO類體系
- (86)文件操作之File類使用
- (87)文件操作之讀取文件
- (88)文件操作之寫文件
- (89)讀取控制臺輸入
- (90)裝飾流使用1
- (91)裝飾流使用2
- (92)IO使用注意問題
- (93)多線程基礎
- (94)多線程實現方式1
- (95)多線程實現方式2
- (96)多線程使用示例1
- (97)多線程使用示例2
- (98)多線程問題及處理1
- (99)多線程問題及處理2
- (100)多線程問題及處理3
- (101)網絡編程概述
- (102)網絡編程技術1
- (103)網絡編程技術2
- (104)網絡編程技術3
- (105)網絡編程技術4
- (106)網絡編程技術5
- (107)網絡協議概念
- (108)網絡編程示例1
- (109)網絡編程示例2
- (110)網絡編程小結