java的线程机制(二) Thread的生命周期

之前讲到Thread的创建,那是Thread生命周期的第一步,其后就是通过start()方法来启动Thread,它会 执行一些内部的管理工作然后调用Thread的run()方法,此时该Thread就是alive(活跃)的,而且我们还可以通 过isAlive()方法来确定该线程是否启动还是终结。

一旦启动Thread后,我们就只能执行一个方 法:run(),而run()方法就是负责执行Thread的任务,所以终结Thread的方法很简单,就是终结run()方法。仔 细查看文档,我们会发现里面有一个方法:stop(),似乎可以用来停止Thread,但是这个方法已经被废除了, 因为它存在着内部的竞争。

我们经常需要一个不断执行的Thread,然后在某个特定的条件下才会终结 它,方法有很多,但最常用的有设定标记和中断Thread两种方式。

我们将之前例子中的Thread改写一 下:

public class RandomCharacterGenerator extends Thread implements CharacterSource {
    static char[] chars;
    static String charArray = "abcdefghijklmnopqrstuvwxyz0123456789";
    static {
        chars = charArray.toCharArray();
    }

    private volatile boolean done = false;

    Random random;
    CharacterEventHandler handler;

    public RandomCharacterGenerator() {
        random = new Random();
        handler = new CharacterEventHandler();
    }

    public int getPauseTime() {
        return (int) (Math.max(1000, 5000 * random.nextDouble()));
    }

    @Override
    public void addCharacterListener(CharacterListener cl) {
        handler.addCharacterListener(cl);
    }

    @Override
    public void removeCharacterListener(CharacterListener cl) {
        handler.removeCharacterListener(cl);
    }

    @Override
    public void nextCharacter() {
        handler.fireNewCharacter(this,
                (int) chars[random.nextInt(chars.length)]);
    }

    public void run() {
        while(!done){
            nextCharacter();
            try {
                Thread.sleep(getPauseTime());
            } catch (InterruptedException ie) {
                return;
            }
        }
    }

    public void setDone(){
        done = true;
    }
}

现在我们多了一个标记:done,这样我们就可以在代码中通过调用setDone()来决定什么时候停止 该Thread。这里使用了volatile关键字,它主要是为了同步。这点会放在同步这里讲。

设定标记的最大问 题就是我们必须等待标记的状态,这样就会造成延迟。当然,这种延迟是无法避免的,但必须想办法缩短到最 小。于是,中断Thread这种方法就有它的发挥地方了。

我们可以通过interrupt()方法来中断Thread, 该方法会造成两个副作用:

1.它会导致任何的阻塞方法都会抛出InterruptedException,我们必须强 制性的捕获这个错误哪怕我们根本就不需要处理它,这也是java的异常处理机制让人诟病的一个地方。

2.设定Thread对象内部的标记来指示此Thread已经被中断了,像是这样:

public void run

(){
     while(!isInterrupted()){
        ...
      }
}

虽然无法避免延迟,但是延迟已经被缩短了。

无论是采用标记还是中断的方法,我们之所以无 法消除延迟的原因是我们无法确定是检查标记先还是调用方法先,这就是所谓的race condition,是线程处理 中永远无法避免的话题。

Thread不仅可以被终结,还可以暂停,挂起和恢复。

Thread原本有 suspend()方法和resume()方法来执行挂起和恢复,但它们和stop()出于同样的原因,都被废除了。

我 们可以通过sleep()方法来挂起Thread,当在指定的时间后,它就会自动恢复。严格意义上讲,sleep并不等同 于suspend,真正的suspend应该是由一个线程来挂起另一个线程,但是sleep只会影响当前的Thread。要想真 正实现挂起和恢复,我们可以使用等待和通知机制,但这个机制最大的问题就是我们的Thread必须使用该技术 来编写。

Thread在终结后,如果有可能,我们还需要对它进行善后。即使Thread已经被终结了,但是 其他对象只要还持有它的引用,它们就可以调用该Thread的资源,这也会导致该Thread无法被回收。

但我们有时候还是希望继续保持该Thread的引用,因为我们想要判别它是否真的已经完成了工作,可以使用 join()方法。join()方法会被阻塞住直到Thread完成它的run()方法,但是这个存在风险:第一次对join()方 法的调用可能会一直被阻塞住很长时间直到Thread真正完成,所以,一般情况下我们还是使用isAlive()方法 来判断。

由于我们可以通过实现一个Runnable接口来定义我们的任务,所以在判断所在线程是否已经 中断的时候,就有一个问题:该任务还没有绑定到任何线程上。我们可以通过currentThread()方法来获得当 前Thread的引用,接着调用isInterrupted()来判断线程是否中断。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索线程
, thread
, 方法
, 标记
, public
, 一个
java线程阻塞中断
thread的生命周期、thread生命周期、java thread生命周期、线程的生命周期、线程生命周期,以便于您获取更多的相关知识。

时间: 2024-08-30 12:08:51

java的线程机制(二) Thread的生命周期的相关文章

java的线程机制(一) 创建线程

现在将1年前写的有关线程的文章再重新看了一遍,发现过去的自己还是照本宣科,毕竟是刚学java的人, 就想将java的精髓之一---线程进制掌握到手,还是有点难度.等到自己已经是编程一年级生了,还是无法将 线程这个高级的概念完全贯通,所以,现在趁着自己还在校,尽量的掌握多点有关线程机制的知识. 我们以一个简单的例子开始下手: public class SwingTypeTester extends JFrame implements CharacterSource{ protected Rando

Spring MVC中Thread的生命周期?

问题描述 刚刚看了论坛老贴:<主题:正确理解ThreadLocal> http://www.iteye.com/topic/103804 ,对 ThreadLocal 的原理大致清楚,想进一步了解一下当前 Thread (即 Thread.currentThread())的生命周期,开始应该是用户发出访问请求了,那结束呢,是一次请求后结束,还是关闭浏览器的时候结束? 解决方案 试问一般情况下服务端如何知道用户的浏览器关闭?当然是请求响应结束,这里的结束指的是服务端结束,浏览器的话还有渲染事要做

浅析Java的线程机制

一 线程的基本概念: 线程是一个程序内部的顺序控制流,一个进程相当于一个任务,一个线程相当于一个任务中的一条执行路径.多进程:在操作系统中能同时运行多个任务(程序):多线程:在同一个应用程序中有多个顺序流同时执行:Java线程是通过java.lang.Thread类来实现的:VM启动时会有一个由主方法(public static void main(){})所定义的线程:以通过创建Thread的实例来创建新的线程每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法r

Android静态变量的生命周期 简单介绍_Android

Android是用Java开发,其静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的时候分配内存的,并且存在于方法区.当类被卸载的时候,静态变量被销毁.在PC机的客户端程序中,一个类被加载和卸载,可简单的等同于jvm进程的启动和结束.那么在Android中呢?用的Dalvik vm也是一样的.不过Android不太突出的进程概念,所以对静态变量的生命周期就会感觉模糊,这种模糊对于值类型是无所谓的,如果是静态的对象引用,则与内存回收.内存泄漏这些问题有关,有必要加深研究和理解

Activity详解(生命周期、以各种方式启动Activity、状态保存,完全退出等)

一.什么是Activity?     简单的说:Activity就是布满整个窗口或者悬浮于其他窗口上的交互界面.在一个应用程序中通常由多个Activity构成,都会在Manifest.xml中指定一个主的Activity,如下设置 <actionandroid:name="android.intent.action.MAIN" /> 当程序第一次运行时用户就会看这个Activity,这个Activity可以通过启动其他的Activity进行相关操作.当启动其他的Activi

Android开发之activity的生命周期详解_Android

本文实例讲述了Android activity的生命周期.分享给大家供大家参考,具体如下: activity类处于android.app包中,继承体系如下: 1.Java.lang.Object 2.android.content.Context 3.android.app.ApplicationContext 4.android.app.Activity activity是单独的,用于处理用户操作.几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通

Android开发之Activity和Fragment生命周期对比图

一.Activity 生命周期 二.Fragment 生命周期 三.对比图 四.测试代码 [java] view plaincopy package com.goso.testapp;      import android.app.Activity;   import android.app.ListFragment;   import android.os.Bundle;   import android.util.Log;   import android.view.LayoutInfla

Android静态变量的生命周期 简单介绍

Android是用Java开发,其静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的时候分配内存的,并且存在于方法区.当类被卸载的时候,静态变量被销毁.在PC机的客户端程序中,一个类被加载和卸载,可简单的等同于jvm进程的启动和结束.那么在Android中呢?用的Dalvik vm也是一样的.不过Android不太突出的进程概念,所以对静态变量的生命周期就会感觉模糊,这种模糊对于值类型是无所谓的,如果是静态的对象引用,则与内存回收.内存泄漏这些问题有关,有必要加深研究和理解

Android开发之activity的生命周期详解

本文实例讲述了Android activity的生命周期.分享给大家供大家参考,具体如下: activity类处于android.app包中,继承体系如下: 1.Java.lang.Object 2.android.content.Context 3.android.app.ApplicationContext 4.android.app.Activity activity是单独的,用于处理用户操作.几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通