Java编程那些事儿96——多线程利用示例1
副标题#e#
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;
}
}
#p#副标题#e#
在该示例代码中,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();
}
}
#p#分页标题#e#
在该示例代码中,实现的道理和前面的雷同,TestTimeBomb2类实现系统线程,成果是启动模仿按时炸弹的线程,并吸收用户的节制台输入。而TimeBombTimerTask类实现模仿按时炸弹的线程,在该类内部包括启动线程的Timer工具,当结构该类的工具时,不只完成该类的初始化,并且启动线程。
在节制Timer启动的线程竣事时,首先竣事当前的TimerTask线程,然后再挪用Timer工具的cancel要领竣事Timer工具的线程,这样才可以真正遏制这种方法启动的线程。
至于利用实现Runnable方法实现线程的方法,和担任Thread类的实现险些一致,读者可以按照第一种方法的实现独自举办实现,这里就不再反复实现了。