## 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)网络编程小结