搜档网
当前位置:搜档网 › Inside Java Thread

Inside Java Thread

Inside Java Thread
Inside Java Thread

深入Java 线程

王伟2009-07-30 一、什么是线程

为了清楚什么是线程,先了解一下程序和进程的概念。

程序就是源代码和文档的集合,如果经过编译后,就是目标平台可执行的指令集合。程序是静态的。

相比之下,进程是动态的。操作系统加载可执行程序后,即产生了一系统进程,由操作系统调度管理。现代操作系统都是多任务多用户的,意味着操作系统可以调度许多进程。进程之间亦可以依赖于操作系统进行通信。进程是重量级的,因为进程的调度需要耗费大量的CPU和内存资源。

线程是进程的进一步划分,可以认为一个进程由多个线程按各自的执行路线运行而组成。由于线程共享同一个进程内存空间,线程间通信、调度开销要比进程之间的通信、调度开销要小得多。因此,现在的应用程序往往会采用多线程编程来提高性能。

二、创建Java线程

Java提供了语言级对线程的支持。Java中线程被抽象为对象,线程的创建需要用到Thread类或者Runnable接口。也就是说线程类的编写有两种方式:一种是扩展Thread类;另一种是实现Runnable接口。无论是哪一种方式,线程的执行体都是run方法。

代码Thread_1,采用扩展Thread类的方式定义线程类

测试类:

代码Thread_2,采用实现Runnable接口的方式定义线程类

测试类:

三、Java线程的状态及常用方法

Java线程状态可以用下表描述:

以下是线程状态过渡示意图:

Thread.start( ) 方法通知线程规化器这个线程已准备就绪,并尽快执行线程,即执行线程类的run方法。这意味着编程只能控制线程进入准备运行状态,何时真正运行则由线程规化器决定。

Thread.sleep( ) 方法将当前线程置入睡眠状态,进入睡眠状态的线程可能被其他线程中断而采取某种行为。睡眠线程被中断时,sleep方法抛出一InterruptException异常。

代码Thread_3

测试类:

输出结果:

在主线程(main方法)中,使用t3.interrupt( )中断了正在休眠的线程t3。实际上,Thread.interrupt( ) 方法只是在目标线程中设置了一个标志,表示它已经被中断,并立即返回。上例中,Thread.sleep( ) 方法检测到t3被中断,因此中断t3的休眠状态并抛出InterruptionException。如果在调用sleep()之前线程已经被interrupt ( )方法标志为中断,sleep( ) 会立即抛出InterruptionException异常。

代码Thread_4:

main( ) 方法为主线程,Thread.currentThread( ) 方法能够获得当前线程的引用,即主线程。在主线程休眠之前,主线程被标识为中断,因此sleep( ) 方法立即抛出InterruptionException异常。

再来看一个例子:

测试类代码:

创建了2个线程t1、t2,t1的优先级为最低,而t2则是最高优先级,如果在线程类Thread_5中没有代码:

线程t1,几乎没有机会获得处理器来执行代码,出于等待状态,加上次代码后,如果是t2获得了处理器,执行完输出后,会通过Thread.yeild( ) 方法主动放弃使用处理器的权利,从而使得t1有机会执行。

对于Thread.stop( ) 、Thread.suspend( ) 、Thread.resume( ) 从Java 1.2之后不再赞成使用,这里不予以介绍。

四、线程并发

先看到一个例子:

代码Thread_6:

代码SharedObject:

测试代码:

测试代码输出:

从输出我们首先可以发现,doWork方法被X线程调用的同时也被Y线程调用。其次我们发现输出结果不正确,每个线程对value累加3次,value 最终结果应该是7,而不是6。

Thread.join( ) 方法的作用为等待线程结束,测试代码中,主线程输出value的结果,需要在线程X、Y都结束的情况下输出。

从上例我们可以得出结论,如果存在多线程线程并发的情况,数据很容易出现不一致的情况。Java多线程编程提供了两种机制来解决数据不一致的问题,分别需要使用到关键字volatile和synchronized。

相关主题