Welcome 微信登录

首页 / 操作系统 / Linux / 浅谈Java线程的生命周期

创建Java线程 在Java程序中创建线程有几种方法。每个Java程序至少包含一个线程:主线程。其它线程都是通过Thread构造器或实例化继承类Thread的类来创建的。 Java线程可以通过直接实例化Thread对象或实例化继承Thread的对象来创建其它线程。在线程基础中的示例(其中,我们在十秒钟之内计算尽量多的素数)中,我们通过实例化CalculatePrimes类型的对象(它继承了Thread),创建了一个线程。 当我们讨论Java程序中的线程时,也许会提到两个相关实体:完成工作的实际线程或代表线程的Thread对象。正在运行的线程通常是由操作系统创建的;Thread对象是由JavaVM创建的,作为控制相关线程的一种方式。 创建线程和启动线程并不相同 在一个线程对新线程的Thread对象调用start()方法之前,这个新线程并没有真正开始执行。Thread对象在其线程真正启动之前就已经存在了,而且其线程退出之后仍然存在。这可以让您控制或获取关于已创建的线程的信息,即使线程还没有启动或已经完成了。 通常在构造器中通过start()启动线程并不是好主意。这样做,会把部分构造的对象暴露给新的线程。如果对象拥有一个线程,那么它应该提供一个启动该线程的start()或init()方法,而不是从构造器中启动它。(请参阅参考资料,获取提供此概念更详细说明的文章链接。) 结束Java线程 Java线程会以以下三种方式之一结束: Java线程到达其run()方法的末尾。 Java线程抛出一个未捕获到的Exception或Error。 另一个Java线程调用一个弃用的stop()方法。弃用是指这些方法仍然存在,但是您不应该在新代码中使用它们,并且应该尽量从现有代码中除去它们。 当Java程序中的所有线程都完成时,程序就退出了。 加入Java线程 ThreadAPI包含了等待另一个线程完成的方法:join()方法。当调用Thread.join()时,调用线程将阻塞,直到目标线程完成为止。 Thread.join()通常由使用线程的程序使用,以将大问题划分成许多小问题,每个小问题分配一个线程。本章结尾处的示例创建了十个线程,启动它们,然后使用Thread.join()等待它们全部完成。 Java线程调度 除了何时使用Thread.join()和Object.wait()外,线程调度和执行的计时是不确定的。如果两个线程同时运行,而且都不等待,您必须假设在任何两个指令之间,其它线程都可以运行并修改程序变量。如果线程要访问其它线程可以看见的变量,如从静态字段(全局变量)直接或间接引用的数据,则必须使用同步以确保数据一致性。 在以下的简单示例中,我们将创建并启动两个线程,每个线程都打印两行到System.out: 1.publicclassTwoThreads{ 2.publicstaticclassThread1extendsThread{ 3.publicvoidrun(){ 4.System.out.println("A"); 5.System.out.println("B"); 6.} 7.} 8.publicstaticclassThread2extendsThread{ 9.publicvoidrun(){ 10.System.out.println("1"); 11.System.out.println("2"); 12.} 13.} 14.publicstaticvoidmain(String[]args){ 15.newThread1().start(); 16.newThread2().start(); 17.} 18.} 我们并不知道这些行按什么顺序执行,只知道“1”在“2”之前打印,以及“A”在“B”之前打印。输出可能是以下结果中的任何一种: 12AB 1A2B 1AB2 A12B A1B2 AB12 不仅不同机器之间的结果可能不同,而且在同一机器上多次运行同一程序也可能生成不同结果。永远不要假设一个线程会在另一个线程之前执行某些操作,除非您已经使用了同步以强制一个特定的执行顺序。