`
klcwt
  • 浏览: 194646 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

线程的生命

阅读更多

创建线程
在 Java 程序中创建线程有几种方法。每个 Java 程序至少包含一个线程:主线程。其它线程都是通过 Thread 构造器或实例化继承类 Thread 的类来创建的。

Java 线程可以通过直接实例化 Thread 对象或实例化继承 Thread 的对象来创建其它线程。在线程基础中的示例(其中,我们在十秒钟之内计算尽量多的素数)中,我们通过实例化 CalculatePrimes 类型的对象(它继承了 Thread),创建了一个线程。

当我们讨论 Java 程序中的线程时,也许会提到两个相关实体:完成工作的实际线程或代表线程的 Thread 对象。正在运行的线程通常是由操作系统创建的;Thread 对象是由 Java VM 创建的,作为控制相关线程的一种方式。

评论:生命有始有终啊,线程也一样。作为他的上帝,管好它,别像人类一样放纵。




创建线程和启动线程并不相同

在一个线程对新线程的 Thread 对象调用 start() 方法之前,这个新线程并没有真正开始执行(注意噢,使用strat才启用线程,run是线程实现的一个方法)。Thread 对象在其线程真正启动之前就已经存在了,而且其线程退出之后仍然存在。这可以让您控制或获取关于已创建的线程的信息,即使线程还没有启动或已经完成了。

通常在构造器中通过 start() 启动线程并不是好主意。这样做,会把部分构造的对象暴露给新的线程。如果对象拥有一个线程,那么它应该提供一个启动该线程的 start() 或 init() 方法,而不是从构造器中启动它。(请参阅参考资料,获取提供此概念更详细说明的文章链接。https://www6.software.ibm.com/developerworks/cn/education/java/j-threads/tutorial/j-threads-8-2.html)


结束线程

线程会以以下三种方式之一结束:

  • 线程到达其 run() 方法的末尾。
  • 线程抛出一个未捕获到的 Exception 或 Error。
  • 另一个线程调用一个弃用的 stop() 方法。弃用是指这些方法仍然存在,但是您不应该在新代码中使用它们,并且应该尽量从现有代码中除去它们。
  • 当 Java 程序中的所有线程都完成时,程序就退出了。




加入线程
Thread API 包含了等待另一个线程完成的方法:join() 方法。当调用 Thread.join() 时,调用线程将阻塞,直到目标线程完成为止。

Thread.join() 通常由使用线程的程序使用,以将大问题划分成许多小问题,每个小问题分配一个线程。本章结尾处的示例创建了十个线程,启动它们,然后使用 Thread.join() 等待它们全部完成。



调度
除了何时使用 Thread.join() 和 Object.wait() 外,线程调度和执行的计时是不确定的。如果两个线程同时运行,而且都不等待,您必须假设在任何两个指令之间,其它线程都可以运行并修改程序变量。如果线程要访问其它线程可以看见的变量,如从静态字段(全局变量)直接或间接引用的数据,则必须使用同步以确保数据一致性。

在以下的简单示例中,我们将创建并启动两个线程,每个线程都打印两行到 System.out:
public class TwoThreads {

    public static class Thread1 extends Thread {
        public void run() {
            System.out.println("A");
            System.out.println("B");
        }
    }

    public static class Thread2 extends Thread {
        public void run() {
            System.out.println("1");
            System.out.println("2");
        }
    }

    public static void main(String[] args) {
        new Thread1().start();
        new Thread2().start();
    }
}
         

我们并不知道这些行按什么顺序执行,只知道“1”在“2”之前打印,以及“A”在“B”之前打印。输出可能是以下结果中的任何一种:

1 2 A B
1 A 2 B
1 A B 2
A 1 2 B
A 1 B 2
A B 1 2
不仅不同机器之间的结果可能不同,而且在同一机器上多次运行同一程序也可能生成不同结果。永远不要假设一个线程会在另一个线程之前执行某些操作,除非您已经使用了同步以强制一个特定的执行顺序。

休眠
Thread API 包含了一个 sleep() 方法,它将使当前线程进入等待状态,直到过了一段指定时间,或者直到另一个线程对当前线程的 Thread 对象调用了 Thread.interrupt(),从而中断了线程。当过了指定时间后,线程又将变成可运行的,并且回到调度程序的可运行线程队列中。

如果线程是由对 Thread.interrupt() 的调用而中断的,那么休眠的线程会抛出 InterruptedException,这样线程就知道它是由中断唤醒的,就不必查看计时器是否过期。

Thread.yield() 方法就象 Thread.sleep() 一样,但它并不引起休眠,而只是暂停当前线程片刻,这样其它线程就可以运行了。在大多数实现中,当较高优先级的线程调用 Thread.yield() 时,较低优先级的线程就不会运行。

CalculatePrimes 示例使用了一个后台线程计算素数,然后休眠十秒钟。当计时器过期后,它就会设置一个标志,表示已经过了十秒。

守护程序线程
我们提到过当 Java 程序的所有线程都完成时,该程序就退出,但这并不完全正确。隐藏的系统线程,如垃圾收集线程和由 JVM 创建的其它线程会怎么样?我们没有办法停止这些线程。如果那些线程正在运行,那么 Java 程序怎么退出呢?

这些系统线程称作守护程序线程。Java 程序实际上是在它的所有非守护程序线程完成后退出的。

任何线程都可以变成守护程序线程。可以通过调用 Thread.setDaemon() 方法来指明某个线程是守护程序线程。您也许想要使用守护程序线程作为在程序中创建的后台线程,如计时器线程或其它延迟的事件线程,只有当其它非守护程序线程正在运行时,这些线程才有用。

示例:用多个线程分解大任务

在这个示例中,TenThreads 显示了一个创建了十个线程的程序,每个线程都执行一部分工作。该程序等待所有线程全部完成,然后收集结果。


/
**
 * Creates ten threads to search for the maximum value of a large matrix.
 * Each thread searches one portion of the matrix.
 */
public class TenThreads {

    private static class WorkerThread extends Thread {
        int max = Integer.MIN_VALUE;
        int[] ourArray;

        public WorkerThread(int[] ourArray) {
            this.ourArray = ourArray;
        }

        // Find the maximum value in our particular piece of the array
        public void run() {
            for (int i = 0; i < ourArray.length; i++) 
                max = Math.max(max, ourArray[i]);                
        }

        public int getMax() {
            return max;
        }
    }

    public static void main(String[] args) {
        WorkerThread[] threads = new WorkerThread[10];
        int[][] bigMatrix = getBigHairyMatrix();
        int max = Integer.MIN_VALUE;
        
        // Give each thread a slice of the matrix to work with
        for (int i=0; i < 10; i++) {
            threads[i] = new WorkerThread(bigMatrix[i]);
            threads[i].start();
        }

        // Wait for each thread to finish
        try {
            for (int i=0; i < 10; i++) {
                threads[i].join();
                max = Math.max(max, threads[i].getMax());
            }
        }
        catch (InterruptedException e) {
            // fall through
        }

        System.out.println("Maximum value was " + max);
    }
}

小结
就象程序一样,线程有生命周期:它们启动、执行,然后完成。一个程序或进程也许包含多个线程,而这些线程看来互相单独地执行。

线程是通过实例化 Thread 对象或实例化继承 Thread 的对象来创建的,但在对新的 Thread 对象调用 start() 方法之前,这个线程并没有开始执行。当线程运行到其 run() 方法的末尾或抛出未经处理的异常时,它们就结束了。

sleep() 方法可以用于等待一段特定时间;而 join() 方法可能用于等到另一个线程完成。


分享到:
评论
1 楼 lxr_0823 2011-02-15  
getBigHairyMatrix()这个方法上报错  让写呢  可是我不会  可以教教么?都不知道大概让写什么……

相关推荐

    java线程生命周期详细讲解

    Java多线程生命周期的讲解,很详细,希望能帮到大家

    线程生命周期.png

    多线程生命周期图解,一分钟了解线程从生到死全过程,图文并茂,通俗易懂,容易记忆。独家原创。欢迎下载。

    线程生命周期流程图

    我根据自己的理解画的这个线程生命流程图,希望对你们有点点的帮助吧!!!

    Delphi多线程生命模拟程序

    《Delphi多线程生命模拟程序详解》 生命模拟程序是一种计算机模拟实验,它尝试通过简单的规则来模拟生物系统的复杂行为。在编程领域,利用 Delphi 这样的高级编程语言来实现多线程的生命模拟程序,可以极大地提高...

    多线程生命模拟程序

    标题中的“多线程生命模拟程序”指的是一个利用多线程技术实现的计算机程序,它模拟了生物体的生命周期和互动。在计算机科学领域,生命模拟通常基于所谓的细胞自动机,如著名的康威生命游戏。这类模拟允许我们观察...

    Java线程生命周期.zip

    Java线程生命周期是Java编程中的核心概念,它关乎程序的并发执行和性能优化。线程在Java中扮演着至关重要的角色,特别是在多任务处理和实时系统中。理解线程的生命周期有助于开发者更有效地管理和控制程序运行流程。...

    线程生命周期.pdf

    以图表形式详细列出java线程生命周期,创建线程,线程就绪,线程阻塞,线程中断,线程唤醒,线程运行之间的关系

    线程生命周期.uml

    线程生命周期.uml

    ruby-线程生命周期及其状态

    ruby|线程生命周期及其状态

    Java多线程(二)、线程的生命周期和状态控制

    ### Java多线程之线程的生命周期和状态控制 #### 一、线程的生命周期 在Java中,线程的生命周期是指线程从创建到结束的整个过程。根据线程的状态变化,我们可以将线程的生命周期划分为以下几个阶段: 1. **新建...

    线程管理和线程的生命周期

    主要是线程基本概念,线程同步。线程的生命周期。做了一个demo。

    Java多线程-线程的生命周期

    线程生命周期的终点是死亡状态。线程在以下三种情况下结束:`run()`方法执行完毕、执行过程中抛出未捕获异常或错误,或者调用已过时的`stop()`方法。 6. 等待(Waiting): 从JDK1.5开始,线程可以进入等待状态,这...

    4初学Java多线程:线程的生命周期.pdf

    在探讨Java多线程和线程生命周期时,我们首先应该明确,Java多线程是Java语言支持并发编程的一个重要特性,其允许同时执行多个任务,以提高程序的执行效率和改善用户体验。Java中的每个线程都有自己的生命周期,由一...

    大漠多线程模板_大漠_大漠多线程_

    模板可能封装了检查和管理线程状态的方法,帮助开发者更好地控制线程生命周期。 6. **异常处理**:多线程环境下的异常处理需要特别注意,因为一个线程的异常可能会中断其他线程。大漠的模板可能包含了优雅的异常...

    多线程线程变量赋值

    在编程领域,多线程是实现并发执行任务的重要...通过`ThreadLocal`,我们可以创建和操作线程特有的变量,避免了数据同步的复杂性,但在使用过程中需要注意内存管理和线程生命周期的管理,以确保程序的健壮性和效率。

    鱼刺多线程注册源码例子(鱼刺多线程稳定框架)

    5. 线程生命周期管理:包括启动、等待、停止和销毁线程的方法,确保程序在所有线程结束后能够正常退出。 深入学习这个例子,开发者可以掌握如何在实际项目中应用多线程技术,提升软件性能,同时理解如何利用专门的...

    前台线程后台线程区别实验

    5. 调整`Thread.IsBackground`属性,观察其对线程生命周期的影响。 通过这个实验,开发者能够更深入地理解C#中的线程管理和并发编程,这对于开发高效、响应性强的应用程序至关重要。在实际开发中,合理利用前台线程...

    PB多线程实现

    6. **线程生命周期管理**:创建线程时要考虑其生命周期,避免过多的线程创建和销毁导致的性能损失。 五、示例代码 这里提供一个简单的PB.NET多线程示例: ```csharp using System.Threading; public class ...

    图解Java线程的生命周期

    正确管理线程生命周期是防止死锁、资源浪费和提高程序效率的关键。合理设计线程间的协作,使用线程池来控制线程数量,以及正确处理异常,都是编写多线程程序时应考虑的重要因素。理解并掌握Java线程的生命周期转换有...

    GaiaThreadNest:用于线程生命周期控制的多线程应用程序框架

    线程生命周期管理 `GaiaThreadNest`的核心功能是线程的生命周期控制。传统的C++线程操作需要直接调用`std::thread`的构造函数创建线程,然后手动管理线程的运行与结束。而`GaiaThreadNest`通过封装这些过程,允许...

Global site tag (gtag.js) - Google Analytics