当前位置: 首页 > 图灵资讯 > 技术篇> Java线程的深入探讨

Java线程的深入探讨

来源:图灵教育
时间:2024-02-22 14:22:31

  1.线程是什么?   一般来说,我们称在计算机中执行的程序为“过程”(Process),而不将其 称为程序(Program)。所谓“线程”(Thread),是“过程”中单一顺序的控制流。 Mac等新兴操作系统,WindowsNT,Windows95等,大多采用多线程的概念 程视为基本执行单位。线程也是Java的重要组成部分之一。

  甚至最简单的Applet也是由多个线程完成的。在Java中,任何Applet paintAWTTT()和update()的方法都是由AWTTE制成的(AbstractWindowToolkit)绘图和事件处理线 Applet的主要里程碑方法是程调用——init(),start(),stop()和destory() ——它是由Applet的应用程序调用的。

  单线程的概念没有什么新的。真正有趣的是在一个程序中同时使用多个线 程来完成不同的任务。有些地方使用轻量化进程(LightweightProcess)来代替线程 ,线程与真实过程的相似之处在于,它们都是单一顺序控制流。然而,线程被认为是轻的 由于它在整个程序的上下文中运行,因此可以使用整个程序共享的资源和程序环境。

  作为一个单一的顺序控制流,必须有一些资源作为运行程序内的必要费用 。例如,必须有执行堆栈和程序计数器。在线程中执行的代码只在其上下文中开始 因此,有些地方用“执行上下文”代替“线程”。

  2.线程属性   要正确有效地使用线程,必须了解线程的各个方面,并了解Java实时系统。

  必须知道如何提供线程体、线程生命周期、实时系统如何调度线程、线程组、 幽灵线程是什么?(DemonThread)。

  (1)线程体   所有操作都发生在线程体中,Java中线程体是从Thread类继承的run()方 Run()方法,或实现Runnable接口的类别。当线程产生并初始化时,实时系统调整 使用它的run()方法。run()代码在方法中实现线程的行为,是线程的主要部分 分。

  (2)线程状态   附图显示了线程在其生命周期的任何时候都能处于状态,并导致状态变化 变的方法。这张图不是一个完整的有限状态图,但它基本上总结了线程中的兴趣和普遍性 的方面。以下是关于线程生命周期的讨论。

  ●新线程态(NewThread)   生成一个Thread对象生成一个新的线程。当线程处于“新线程”状态时,只是 空线程对象尚未分配到系统资源。因此,它只能启动或终止。任何其他操 作都会引起异常。

  ●可运行态(Runnable)   start()方法产生运行线程所需的资源,调度线程执行,并调用线程的runn ()方法。此时,线程处于可操作状态。这种状态不称为运行态,因为此时的线程不是 总是占用处理机。特别是对于只有一台处理机的PC,任何时候都只能有一台处理机 线程占用处理器处于可操作态。Java通过调度实现多线程共享处理器。

  ●非运行态(NotRunnable)   当发生以下事件时,线程进入非运行态。   ①suspend()调用方法;   ②sleep()调用方法;   ③wait()用于等待条件变量;   ④I/O等待线程。

  ●死亡态(Dead)   当run()方法返回,或者其他线程调用stop()方法时,线程进入死亡状态。通常Appl et采用stop()方法终止其生成的所有线程。   (3)线程优先级   虽然我们说线程并发运行。但事实往往并非如此。正如前面提到的,当 当系统中只有一个CPU时,在单个CPU的情况下按一定顺序执行多线程称为调度(schedu ling)。Java采用简单固定的调度方法,即固定优先调度。这种算法是 根据可操作状态线程的相对优先级进行调度。当线程生成时,它继承了原始线程 优先级。必要时可修改优先级。在任何时候,如果有多个线程等待运行, 系统选择优先级最高的可操作线程运行。只有当它停止,自动放弃,或者因为某种原因 原因是非运行状态下的低优先级线程可以运行。如果两个线程有相同的优先级,那么它 它们将交替运行。   Java实时系统的线程调度算法在任何时候都是强制性的,如果一个比其他线更好 程优先级高的线程状态变为可操作状态,实时系统将选择该线程进行操作。   (4)幽灵线程   任何Java线程都可以成为幽灵线程。它作为在同一过程中运行的对象 和线程服务提供商。例如,HotJava浏览器中有一个幽灵叫做“后台图片阅读器” 线程,它从文件系统或网络中读取图片,是需要图片的对象和线程。

  幽灵线程是应用程序中典型的独立线程。它为同一应用程序中的其他对象和线程提供服务 服务。run()方法的幽灵线程一般是无限循环,等待服务请求。   (5)线程组   每一个Java线程都是某一线程组的成员。线程组为多个线程集提供了一种机制 它们可以在一个对象中进行整体操作。例如,您可以用一种方法调用它来启动或悬挂 组内的所有线程。由ThreadGroup类实现Java线程组。

  当线程生成时,可以指定线程组或实时系统将其放入缺失的线程组中。 线程只能属于一个线程组,线程生成后不能改变线程组。

  3.多线程序   多线程的好处就不多说了。然而,它也带来了一些新的麻烦。只要 特别注意设计程序,克服这些麻烦并不难。   (1)同步线程   在执行过程中,必须考虑与其他线程共享数据或协调执行状态。这就 需要同步机制。Java中的每个对象都有一把锁对应。但Java不提供单独的lo 操作ck和unlock。它由高层结构隐式实现,以保证操作的对应性。(然而,我们注意到了 Java虚拟机提供单独的monitorenter和monitorexit指令来实现lock和unlo ck操作。)   synchronized语句计算对象引用,试图锁定对象并完成 锁操作前停止处理。Synchronized语句体在锁操作完成后得到执行。当语句体执行时 解锁操作自动完成(无论正常或异常)。作为面向对象的语言,synchronized 经常与方法连用。一个更好的方法是,如果一个变量被一个线程赋值,并且由其他线程赋值 程引用或赋值,所有对变量的访问都必须在synchromized语句或synch中 在ronized方法中。   现在假设线程1和线程2必须访问某个数据区,并要求线程1访问 只有synchronized才能解决问题。Unix或Windows Simaphore可以在NT中实现。Java不提供。wait()和notii在Java中提供 fy()机制。使用如下:   synchronizedmethod-(){callbythread1.   ∥accessdataarea;   available=true;   notify()   }   synchronizedmethod-2(…){∥calbythread2.   while(!available)   try{   wait();∥waitfornotify().   }catch(InterruptedExceptione){   }   ∥accessdataarea   }   其中available是类成员变量,初始值为false。   假如在method-2中检查available为假,则调用wait()。wait()作用是使线 程2进入非运行状态并解锁。在这种情况下,method-线程1可以调用1。当执行 notify()后。线程2由非运行态转变为可运行态。调用method-1后返回。线程2 您可以重新锁定对象,并在成功锁定后执行wait()返回的指令。这种机制也可以适用 其他更复杂的情况。   (2)死锁   若程序中有几个竞争资源并发线程,则保证平衡非常重要。系统均衡 在执行过程中,每个线程都能充分访问有限的资源。系统中没有饿死和死锁。 线程。Java不提供死锁检测机制。对于大多数Java程序员来说,防止死锁是必要的 更好的选择。防止死锁最简单的方法就是引入竞争资源的序列号,如果一条线 程需要几个资源,所以必须先获得小序号资源,再申请大序号资源。

  4.小结   线程是Java的重要组成部分,多线程是Java的一个特点。尽管Java的同步互斥并非如此 和某些系统一样丰富,但适当使用它们也能得到满意的效果。