回健永
(天津机电职业技术学院,天津市 300131)
基于Java语言的多线程机制的实现
回健永
(天津机电职业技术学院,天津市 300131)
Java语言是目前使用最为广泛的网络编程语言之一。文章首先分析了多线程的机制及其特性,然后通过实例来研究如何用创建 Thread类的子类和实现Runnable接口两种不同方法实现多线程的编程。
Java;多线程;Thread类;Runnable接口
Java是少数的几种支持“多线程”的语言之一,它的一个重要功能特点就是内置对多线程的支持。
多线程指的是在单个进程中可以同时运行多个不同的线程,执行不同的任务。使用多线程技术,可以使编程人员很方便地开发出能同时处理多个任务的功能强大的应用程序。多线程的程序能更好地表述和解决现实世界的具体实际问题,是计算机应用开发和程序设计的一个必然发展趋势。
1.线程(thread)的定义
线程是指进程中单一顺序的控制流,又称为轻量级进程。要说清楚这个概念,要与进程结合起来分析。线程是比进程更小的执行单位。一个进程在其执行过程中,可以产生多个线程,形成多条执行点,每条执行点即每个线程。线程有它自身的产生、存在和消亡的过程,它是一个动态的概念。线程很像进程,它们在概念上是相关的。它们都是代表着程序当前的运行情况,都是执行一定的任务,而且它们都是可以并行并发执行的。
2.线程的状态与生命周期
每个Java程序都有一个默认的主线程,对于Java的应用程序,主线程是main()方法执行的线索;对于App let程序,主线程是指挥浏览器加载并执行Java App let程序的线索。要想实现多线程,必须在主线程中创建新的线程对象。任何一个线程,在它的一个完整生命周期中通常具有创建、就绪、运行、阻塞和终止五种状态。在给定的时间点上,一个线程只能处于一种状态。图1显示了一个Java线程在它的生命周期中的各个状态。
图1 线程的生命周期
3.线程的调度及优先级
每个线程都有一个优先级,它在线程被创建时其优先级是由创建它的线程所决定的;也可以在线程创建之后的任意时刻通过调用setPriority的方法来修改线程的优先级。线程的优先级是在M IN_PRIORITY和MA X_PRlORITY范围内的一个整数值,数值越大,代表线程的优先级越高。
当一个线程进入运行状态之后,这个线程就称为是被“调度”或被线程调度管理器选中了。在Ja2 va系统中,线程调度依据优先级基础上的“先到先服务”原则。在任意时刻,当有多个线程处于可运行状态,运行系统总是挑选一个优先级最高的线程执行,只有当线程停止、退出或者由于某种原因不执行的时候,低优先级的线程才可以被执行。如果当高优先级的线程处于阻塞状态,并且CPU处于空闲时,低优先级的线程会被调度执行;另外若有两个相同优先级的线程同时等待执行时,运行系统会以round-robin的方式选择一个执行。
在Java中,实现多线程的应用有两种方式:一种是继承 Thread类来创建对象用户,另一种是声明实现了Runnable接口的类。两种方式都需要使用到Java基础类库中的Thread类及其方法。
1.通过继承 Thread类实现多线程
用Thread类实现多线程,用户需要在程序中创建自己的 Thread类的子类和重新定义一个自己的run()方法,这个run()方法中包含了用户线程的操作。run()方法是定义在 Thread类里的一个方法,因此把线程的程序代码编写在run()方法内,事实上所做的就是覆写的操作。这样在程序需要建立线程时,它只需要创建一个已定义好的Thread类的子类的实例就可以了。用Thread类实现多线程定义的语法如下:
class类名称extends Thread //从 Thread类扩展出子类
{
属性……
方法……
修饰符 run(){ //覆写 Thread类里的run()方法
以线程处理的程序;}
}
用此方法,在一个Java App lication程序中定义两个类,一个是程序的主类 TestThread,另一个是用户自定义的 Thread类的子类p rimeThread。程序的主线程,即 TestThread主类的main()方法首先根据用户输入的命令行参数创建一个p rimeThread类的对象,并调用start()方法启动这个子线程对象,使之进入就绪状态。主线程首先输出一行信息表示自己在活动,然后调用sleep()方法使自己休眠一段时间以便子线程获取处理器,进入运行状态的子线程将检查一个数值是否是素数并显示出来,然后也休眠一段时间以便父线程获得处理器。获得处理器的父线程将显示一行信息表示自己在活动,然后再休眠……每次子线程启动都检查一个新的增大一个的数值是否为素数并打印,直至该数大于其预定的上限。此时子线程从run()方法返回并结束其运行,然后主线程也结束。
2.通过实现Runnable接口实现多线程
用创建Thread子类的方法虽然简便易用,但是要求必须有一个以 Thread为父类的用户子类。假设用户子类需要有另一个父类,则根据Java程序只允许单一继承的原则,就不能用 Thread类产生线程了,因为Java不允许多继承,这时我们可以考虑使用Runnable接口的方法来创建线程。其定义的语法如下:
class类名称 imp lem ents Runnable //实现Runnable接口
{
属性……
方法……
修饰符 run(){ //覆写 Thread类里的run()方法
以线程处理的程序;}
}
Runnable接口只有一个方法run(),实现这个接口就必须要定义run()方法的具体内容,用户新建线程的操作也由这个方法来决定。Runnable接口中的这个run()方法是一个较特殊的方法,它可以被运行系统自动识别和执行。定义好run()方法之后,当用户程序需要建立新线程时,只要以这个实现了run()方法的类为参数创建系统类Thread的对象,就可以把用户实现的run()方法继承过来。所以,一个实现了Runnable接口的类实际上定义了一个主线程之外的新线程的操作,而定义新线程的操作和执行流程,是实现多线程应用的最主要工作之一。
3.两种实现机制的比较
不管实现了Runnable接口还是继承了 Thread类,两种多线程机制运行的结果都是一样的。经分析可见,实现Runnable接口相对于继承Thread类来说,有如下三个显著优势。
(1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好地体现了面向对象的设计思想。
(2)可以避免由于Java的单继承特性带来的局限。
(3)增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。
由于 Thread类实现了Runnable接口,也就是说 Thread类也是Runnable接口的一个子类。在实际的开发中,几乎所有多线程的应用都可以使用实现Runnable接口。
4.多线程实现应用实例
在程序中,多线程的实现可以通过创建 Thread类的子类和通过实现Runnable接口两个途径来完成。无论采用哪种途径,程序员在编程中可以用定义用户线程的run()方法与建立用户线程实例来控制两个关键性操作。用实现Runnable接口的方法实现多线程程序如下:
import java.app let.App let;
import java.aw t.3;
public class TestRunnable extends App let imp lem ents Runnable//Java App let主类
{
Label p romp t1=new Label(“第一个子线程”);
Label p romp t2=new Label(“第二个子线程”);
TextField threadFirst=new TextField(14);
TextField threadSecond=new TextField(14);
Thread threadl,thread2;
int countl=O,count2=0;
public void init()
{
add(p romp t1);
add(threadFirst);
add(p romp t2);
add(threadSecond);}
public void start()
{
thread1=new Thread(this,“FirstThread”);
thread2=new Thread(this,“Second Thread”);
thread1.start();//启动线程对象,进入就绪状态
thread2.start();}
public void run()//实现Runnable接口的run()方法,在该线程启动时自动执行
{
String currentRunning;
w hile(true)
{
try
{//使当前活动线程休眠0到3秒
Thread.sleep((int)(M ath.random()3 30000));}
catch(Interrup ted Excep tion e){}
currentRunning=Thread.currentThread().getName();
if(currentRunning.equals(“FirstThread”))
{countl++;
threadFirst.setText(“线程 1”第 +countl+“次被调度”);}
else if(currentRunning.equals(“Second Thread”)){
count2+ +;
threadSecond.setText(“线程2第”+count2+”次被调度”);}
}}}
这是一个Java App let,所以程序的主类 TestRunnable必须是App let类的子类;同时它还实现了Runnable接口并具体实现了run()方法。在TestRunnable中创建了两个子线程,都是Thread类的对象。这两个对象的构造函数指明它们将继承当前类中的run()方法,即它们被调度时将执行这个run()方法。这个run()方法将首先休眠一段随机的时间,然后统计当前活动(即获得了处理器的)线程被调度次数并显示在相应的文本框中。
[1]李相国等.Java实例精通[M].北京:机械工业出版社,2009.
[2]印旻.Java语言与面向对象程序设计[M].北京:清华大学出版社,2002.
[3]袁加全.基于Java多线程的有限元并行计算的研究[D].天津:天津工业大学,2005.
The Imp lem entation of M ulti-Th read M echanism Based on Java L anguage
HU IJian-yong
(Tianjin Vocational College of M echanics and Electricity,Tianjin 300131 China)
Java language is one of the most popular p rogramm ing languages,w hich has the fea2 tures of being simp le,transportable,flexible and multi-threaded.This article first makes analyses on the mechanism and characteristics of m ulti-thread system and then makes some researches on how to build the subtypes of the Thread and how to imp lement them ulti-thread p rogramm ing by using Runna2 ble interface.
Java;multi-thread system;Thread;Runnable interface
TP311
A
1673-582X(2011)08-0058-04
2011-05-30
回健永(1974-),男,天津市人,大学本科学历,天津机电职业技术学院讲师,主要研究方向为计算机应用技术、软件工程。