线程的生命周期.docx

上传人:b****3 文档编号:888542 上传时间:2022-10-13 格式:DOCX 页数:9 大小:20.78KB
下载 相关 举报
线程的生命周期.docx_第1页
第1页 / 共9页
线程的生命周期.docx_第2页
第2页 / 共9页
线程的生命周期.docx_第3页
第3页 / 共9页
线程的生命周期.docx_第4页
第4页 / 共9页
线程的生命周期.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

线程的生命周期.docx

《线程的生命周期.docx》由会员分享,可在线阅读,更多相关《线程的生命周期.docx(9页珍藏版)》请在冰豆网上搜索。

线程的生命周期.docx

线程的生命周期

创建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.outpublicclassTwoThreads{

  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

  不仅不同机器之间的结果可能不同,而且在同一机器上多次运行同一程序也可能生成不同结果。

永远不要假设一个线程会在另一个线程之前执行某些操作,除非您已经使用了同步以强制一个特定的执行顺序。

线程的生命周期

与人有生老病死一样,线程也同样要经历开始(等待)、运行、挂起和停止四种不同的状态。

这四种状态都可以通过Thread类中的方法进行控制。

下面给出了Thread类中和这四种状态相关的方法。

    // 开始线程

   public void start( );

   public void run( );

    // 挂起和唤醒线程

   public void resume( );     // 不建议使用

   public void suspend( );    // 不建议使用

    public static void sleep(long millis);

   public static void sleep(long millis, int nanos);

   // 终止线程

   public void stop( );       // 不建议使用

    public void interrupt( );

   // 得到线程状态

    public boolean isAlive( );

    public boolean isInterrupted( );

   public static boolean interrupted( );

   // join方法

    public void join( ) throws InterruptedException;

一、创建并运行线程

线程在建立后并不马上执行run方法中的代码,而是处于等待状态。

线程处于等待状态时,可以通过Thread类的方法来设置线程不各种属性,如线程的优先级(setPriority)、线程名(setName)和线程的类型(setDaemon)等。

当调用start方法后,线程开始执行run方法中的代码。

线程进入运行状态。

可以通过Thread类的isAlive方法来判断线程是否处于运行状态。

当线程处于运行状态时,isAlive返回true,当isAlive返回false时,可能线程处于等待状态,也可能处于停止状态。

下面的代码演示了线程的创建、运行和停止三个状态之间的切换,并输出了相应的isAlive返回值。

package chapter2;

public class LifeCycle extends Thread

{

    public void run()

    {

        int n = 0;

        while ((++n) < 1000);        

    }

     

    public static void main(String[] args) throws Exception

    {

        LifeCycle thread1 = new LifeCycle();

        System.out.println("isAlive:

 " + thread1.isAlive());

        thread1.start();

        System.out.println("isAlive:

 " + thread1.isAlive());

        thread1.join();  // 等线程thread1结束后再继续执行 

        System.out.println("thread1已经结束!

");

        System.out.println("isAlive:

 " + thread1.isAlive());

    }

}

要注意一下,在上面的代码中使用了join方法,这个方法的主要功能是保证线程的run方法完成后程序才继续运行,这个方法将在后面的文章中介绍

   上面代码的运行结果:

isAlive:

 false

isAlive:

 true

thread1已经结束!

isAlive:

 false

二、挂起和唤醒线程

一但线程开始执行run方法,就会一直到这个run方法执行完成这个线程才退出。

但在线程执行的过程中,可以通过两个方法使线程暂时停止执行。

这两个方法是suspend和sleep。

在使用suspend挂起线程后,可以通过resume方法唤醒线程。

而使用sleep使线程休眠后,只能在设定的时间后使线程处于就绪状态(在线程休眠结束后,线程不一定会马上执行,只是进入了就绪状态,等待着系统进行调度)。

虽然suspend和resume可以很方便地使线程挂起和唤醒,但由于使用这两个方法可能会造成一些不可预料的事情发生,因此,这两个方法被标识为deprecated(抗议)标记,这表明在以后的jdk版本中这两个方法可能被删除,所以尽量不要使用这两个方法来操作线程。

下面的代码演示了sleep、suspend和resume三个方法的使用。

package chapter2;

public class MyThread extends Thread

{

    class SleepThread extends Thread

    {

        public void run()

        {

            try

            {

                sleep(2000);

            }

            catch (Exception e)

            {

            }

        }

    }

    public void run()

    {

        while (true)

            System.out.println(new java.util.Date().getTime());

    }

    public static void main(String[] args) throws Exception

    {

        MyThread thread = new MyThread();

        SleepThread sleepThread = thread.new SleepThread();

        sleepThread.start(); // 开始运行线程sleepThread

        sleepThread.join();  // 使线程sleepThread延迟2秒

        thread.start();

        boolean flag = false;

        while (true)

        {

            sleep(5000);  // 使主线程延迟5秒

            flag = !

flag;

            if (flag)

                thread.suspend(); 

            else

                thread.resume();

        }

    }

}

从表面上看,使用sleep和suspend所产

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 其它语言学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1