摘要:由于在Java语言提供了线程支持,系统资源的利用率得以提高,系统性能得到改善。文章在分析Java多线程的基础上,对如何实现一个多线程,如何实现同步,进行了简要分析。
关键词:Java;多线程;线程机制
中图分类号:TP312 文献标识码:A 文章编号:1009-2374(2014)02-0064-03
1 概述
多线程概念是相对于单线程而说的。计算机指令是在处理器中一条条串行执行的,计算机之所以给人的感觉是多任务同时执行,是因为把处理器时间分为多个比较短的时间片,然后把这些时间片分配给等待处理器时间片的进程中的线程。由于线程间的切换速度非常快,令人感觉同时运行这些线程。
Java语言内置了多线程机制,多线程机制是Java语言的重要特征。通过多线程运行机制来支持多任务和并行处理是Java语言的优点之一,大大简化了多线程应用程序的开发。至今,随着计算机技术的飞速发展和计算机网络的大面积普及以及云计算的逐渐发展,多处理器的计算机已经司空见惯,在这种前景下,Java多线程机制在很多软件开发设计中得到了普遍应用。因此,深入探讨并研究Java多线程机制有利于提高整个应用系统的性能。
2 线程的状态与生命周期
线程的生命周期经历新建、可运行、阻塞、等待、休眠、终止6种状态,我们把线程从新建到终止的状态变化过程称为生命周期。线程的状态转换如图1所示。
2.1 新建
使用new运算符创建一个Thread类或其子类的对象时,线程就处于新建状态,新建的线程已拥有了相应的内存空间,该状态的线程通过调用start()方法进入就绪状态。
2.2 可运行
正在JVM中执行的线程处于可运行状态,该状态下的线程就可以从新建它的主线程脱离出来独立开始自己的生命周期。
2.3 阻塞
线程占用处理器资源期间,当前的线程执行某个操作后进入受阻塞并等待某个监视器锁,该线程处于阻塞状态。进入阻塞状态的线程当消除阻塞原因时,才可以结束当前状态,重新回到可运行状态,等待处理器资源。
2.4 等待
线程占用处理器资源期间,当前的线程執行wait()方法后,进入无限期地等待另一个线程来执行某一特定操作,该线程处于阻塞状态。
2.5 休眠
线程占用处理器资源期间,执行sleep(int millsecond)方法后线程进入休眠状态,进入休眠状态的线程并不释放运行资源,等待参数millsecond指定的毫秒时间后,可以从中断处继续运行。
2.6 终止
退出的线程处于终止状态。线程的终止原因有两个:一个是run()方法中的全部代码执行完毕,另一个是调用stop()方法终止线程的执行。
图1 线程的状态转换图
3 线程的优先级
Java语言由调度器来管理Java虚拟机(JVM)中的线程,它设定了线程的重要程度,把优先级分成1~10个级别,并用Thread类中的常量来表示了这些级别。如果大量的线程在就绪队列中等候处理器资源时,优先级高的线程获得处理器时间片的机会就越高。但是,多个线程等待一个锁的时候,不一定优先级高的先执行。并不是每个操作系统都会按照优先级来选择线程,有些操作系统并不看这个优先级。虽然线程默认的优先级为5,但是我们可以通过setPriority(int i)方法设置线程的优先级,需要注意的是设置后优先级范围一定要在1~10内,否则会出现异常。也可以通过getPriority()方法读取线程的优先级。为提高程序的可移植性,不建议手工调整线程的优先级。
4 多线程的实现方法
Java语言的线程是使用Thread类来创建的,当Thread类创建对象时,就产生了一个新的线程。采用两种途径实现多线程机制:一种是使用Thread类创建多线程,另一种使用Runnable接口创建多线程。
4.1 使用Thread类创建多线程
使用Thread类创建多线程时,编写Thread类子类,在子类中定义run()方法覆盖父类的run()方法,这个run()方法称为线程体,该方法中包含有线程操作的代码,这些操作代码就是线程所要执行的程序代码。
实现代码如下:
public class MyThread extends Thread{
public void run(){//覆盖Thread类的run()方法
...// 省略代码
}
public static void main(String args[]){
MyThread mt=new MyThread ();//创建线程
mt.start();//启动线程
}
}
使用继承Thread类的方式实现多线程机制,可以在子类中增加新的成员变量,使线程具有某种属性;也可以在子类中新增加方法,使线程具有某种功能。但是这种方法实现线程也避免不了单继承的局限性,若某一个类已经继承了Thread类,那么它没有办法再继承其
他类。
4.2 使用Runnable接口创建多线程
在Java中,可以使用Runnable接口创建多线程,这种方法能够避免通过Thread类创建多线程的单继承的局限,因此使用面比较广泛。
实现Runnable接口的类来实例化一个目标对象,当初始化Thread类或它的子类的线程对象时,把目标对象作为参数传递给这个线程对象。Runnable接口只有一个run()方法,当Thread类对象调用start()方法时自动调用Runnable对象的run()方法,执行该方法体的程序代码。
实现代码如下:
public class MyThread implements Runnable{
public void run(){//覆蓋Thread类的run()方法
...//具体线程代码
}
public static void main(String args[]){
MyThread mt=new MyThread();
Thread thread1=new Thread(mt);//创建线程
//或者new Thread(new MyThread());
thread1.start();//启动线程
}
}
5 线程的同步机制
多线程的应用程序中,两个或多个线程需要共享同一片存储空间,在带来方便的同时,也导致线程共享资源发生冲突,此时我们可以使用Java语言提供的同步机制来解决以上的冲突问题,该同步机制是synchronize关键字。使用synchronize关键字可以控制同一时间只有一个线程使用共享资源,它包括两种方法:一种是synchronize方法,另一种就是synchronized块。
5.1 synchronize方法
将访问共享资源的方法都标记为synchronized,用该标记修饰的方法主要来控制对类成员变量的访问。类实例和锁是一一对应的,当获得需要调用synchronize方法的类实例的锁时,synchronize方法才可以执行,而且它开始执行直到完毕为止独占锁。这时其他调用synchronize方法的线程进入阻塞,一直到获得释放锁为止。语法格式如下:
public synchronized void 方法名(参数列表){//定义一个同步方法
...//省略代码
}
5.2 synchronized块
Java语言中除了使用synchronize方法来设置同步,还可以使用synchronized块来设置同步。如果使用前者来修饰一个比较大的方法时,也会锁住了不需要锁住的字段,导致程序运行效率降低。后者是把程序的某段代码使用synchronized块来修饰,跟前者比它可以减少程序的同步区域。所以我们可以使用synchronized块来修饰语句块,能够弥补synchronize方法修饰的缺陷。使用synchronized块的语法格式如下:
synchronized(表达式){//定义一个同步块,表达式的结果是当前对象
...//省略代码
}
6 结语
支持多线程技术是Java语言的特性之一,多线程使程序可以同时存在多个执行片段,它可以提高程序的工作效率并提高程序的技术可行性。多线程技术广泛应用于与网路有关的程序设计中,因此研究多线程技术,对于网路编程技术至关重要。但是在实际运用中,如果不能充分考虑多线程问题,不但不能提高程序效率,反而增加程序运行的负担。因此合理地使用多线程是减轻处理器的负担、提高运行效率的关键所在,在以后的研究中有待于全面的展开分析,进一步探索多线程的有关问题。
参考文献
[1] 彭德林,李德友.Java程序设计技能教程[M].北
京:中国水利水电出版社,2009.
[2] 耿祥义,张跃平.Java程序设计实用教程[M].北
京:人民邮电出版社,2010.
[3] 张宇,张悦.Java多线程机制的研究[J].信息与电
脑,2011,(3).
作者简介:李娟(1977—),女,内蒙古呼和浩特人,呼和浩特民族学院计算机系讲师,硕士,研究方向:计算机软件技术、蒙古文信息处理的教学。