Java线程

Java是基于操作系统级的多线程环境之上设计的,Java的运行器依靠多线程来执行任务,并且所有类库在设计时都考虑到多线程机制。

 

一、Java线程的结构

Java支持一种“抢占式”(preemptive)调度方式。线程从产生到消失,可分5个状态:

Newborn

线程在己被创建但未执行这段时间内,处于一个特殊的"Newborn"状态,这时,线程对象己被分配内存空间,其私有数据己被初始化,但该线程还未被调度。此时线程对象可通过start()方法调度,或者利用stop()方法杀死.新创建的线程一旦被调度,就将切换到"Runnable"状态。

Runnable

Runnable意即线程的就绪状态,表示线程正等待处理器资源,随时可被调用执行。处于就绪状态的线程事实上己被调度,也就是说,它们己经被放到某一队列等待执行。处于就绪状态的线程何时可真正执行,取决于线程优先级以及队列的当前状况。线程的优先级如果相同,将遵循"先来先服务"的调度原则。

线程依据自身优先级进入等待队列的相应位置。某些系统线程具有最高优先级,这些最高优先级线程一旦进入就绪状态,将抢占当前正在执行的线程的处理器资源,当前线程只能重新在等待队列寻找自己的位置.这些具有最高优先级的线程执行完自己的任务之后,将睡眠一段时间,等待被某一事件唤醒.一旦被唤,这些线程就又开始抢占处理器资源。这些最高优先级线程通常用来执行一些关键性任务,如屏幕显示。

低优先级线程需等待更长的时间才能有机会运行。由于系统本身无法中止高优先级线程的执行,因此,如果你的程序中用到了优先级较高的线程对象,那么最好不时让这些线程放弃对处理器资源的控制权,以使其他线程能够有机运行。

Running

"Running"(运行)状态表明线程正在运行,该线己经拥有了对处理器的控制权,其代码目前正在运行。这个线程将一直运行直到运行完毕,除非运行过程的控制权被一优先级更高的线程强占。

综合起来,线程在如下3种情形之下将释放对处理器的控制权:

1.主动或被动地释放对处理器资源的控制权。这时,该线程必须再次进入等待队列,等待其他优先级高或相等线程执行完毕。

2.睡眠一段确定的时间,不进入等待队列。这段确定的时间段到期之后,重新开始运行。

3.等待某一事件唤醒自己。

Blocked

一个线程如果处于"Blocked"(堵塞)状态,那么暂时这个线程将无法进入就绪队列。处于堵塞状态的线程通常必须由某些事件才能唤醒。至于是何种事件,则取决于堵塞发生的原因:处于睡眠中的线程必须被堵塞一段固定的时间;被挂起、或处于消息等待状态的线程则必须由一外来事件唤醒。

Dead

Dead表示线程巳退出运行状态,并且不再进入就绪队列.其中原因可能是线程巳执行完毕(正常结束),也可能是该线程被另一线程所强行中断(kill)。

 

二、创建和使用线程的基本方法

1.线程的产生

在Java语言中,可采用两种方式产生线程:一是实现一个Runnable界面,二是扩充一个Thread类.java.lang中定义了一个直接从根类Object中派生的Thread类.所有以这个类派生的子类或间接子类,均为线程。在这种方式中,需要作为一个线程执行的类只能继承、扩充单一的父类。下面的例子通过扩充Thread类,用该线程自己的实现来覆盖Thread.run(),产生一个新类Counter。run()方法是Counter类线程所作的全部操作.

importjava.lang.*;

publicclassCounterextendsThread

{

publicvoidrun()

{....}

}

实现Runnable界面是最常用的产生线程的方法,它打破了扩充Thread类方式的限制。

Java语言源码中,Runnable界面只包含了一个抽象方法,其定义如下:

packagejava.lang.*;

publicinterfaceRunnable{

publicabstractvoidrun();

}

所有实现了Runnable界面的类的对象都可以以线程方式执行.下面的例子产生与上面例子相同的类.可以看到counter类中使用了一个Thread类的变量.

importjava.lang.*;

publicclasscounterimplementsRunnable

{  

ThreadT;

publicvoidrun(){...}

}

2、基本方法

publicsynchronizedvoidstart()

启动线程对象,调用其run()方法,随即返回。

pubilcfinalvoidstop()

停止线程的执行。

publicfinalvoidresume()

唤醒被挂起的线程。只在调用suspend()之后有效。

publicfinalvoidsuspend()

挂起线程的执行。

publicstaticvoidyield()

暂时中止当前正在执行的线程对象的运行。若存在其他线程,则随后调用下一个线程。

publicstaticvoidsleep(longmills)throwsInterruptedException

使当前正处运行状态的线程睡眠mills毫秒。

publicfinalvoidwait()throwsInterruptedException

使线程进入等待状态,直到被另一线程唤醒

publicfinalvoidmotify()

把线程状态的变化通知给另一等待线程。

 

三、线程的同步

线程的使用,主要在于一个进程中多个线程的协同工作,所以线程的同步就很重要。线程的同步用于线程共享数据,转换和控制线程的执行,保证内存的一致性。

在Java中,运行环境使用程序(Monitor)来解决线程同步的问题。管程是一种并发同步机制,它包括用于分配一个特定的共享资源或一组共享资源的数据和方法.

Java为每一个拥有synchronized方法的对象实例提供了一个唯一的管程。为了完成分配资源的功能,线程必须调用管程入口。管程入口就是synchronized方法入口。当调用同步(synchronized)方法时,该线程就获得了该管程。

管程边界上实行严格的互斥,在同一时刻,只允许一个线程进入管程;当管程中已有了一个线程时,其它希望进入管程的线程必须等待,这种等待是由管程自动管理的。

如果调用管程入口的线程发现资源已被分配,管程中的这个线程将调用等待操作wait()。进入wait()后,该线程放弃占用管程,在管程外面等待,以便其它线程进入管程。

最终,占用资源的线程将调用一个管程的入口把资源归还给系统,此时,该线程需调用一个通知操作notify(),通知系统允许其中一个等待的线程获得管程并得到资源。被通知的线程是排队的,从而避免无限拖延。

在Java.lang中提供了用来编写管程的两个方法:notify()和wait()。此外还有notifyAll(),它通知所有等待的线程,使它们竞争管程,结果是其中一个获得管程,其佘返回等待状态。

 

四、线程的控制

线程的控制分为停止线程和启动线程。

publicfinalvoidsuspend()

挂起线程的执行。

publicfinalvoidresume()

唤醒被挂起的线程。使一个暂停的线程可用于调度。

因为线程的调度为抢占式机制,也可使用线程的优先级来对线程进行控制。

publicfinalvoidsetPriority(intnewPriority)

设置线程优先级。

publicfinalintgetPriority()

获取并返回线程的优先级。

线程的优先级用于在运行队列中给线程排序,Java提供的抢占式调度,使得高级别的线程先运行。

 

五、线程的应用

在实际应用中,线程使用的范围很广,可用于控制实时数据处理、快速的网络服务,还有更快的图象绘制和打印,以及数据库中的数据的取回和处理等等。在Java中一个在不停运行的提供一些基本服务的例子是垃圾收集线程,垃圾收集线程,。该线程由Java虚拟机提供。它扫描程序中不再被访问的变量,将其所占的系统资源释放给系统。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值