之前讲到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()来判断线程是否中断。

一步一步掌握java的线程机制(二)----Thread的生命周期的更多相关文章

  1. java中线程机制

    java中线程机制,一开始我们都用的单线程.现在接触到多线程了. 多线性首先要解决的问题是:创建线程,怎么创建线程的问题: 1.线程的创建: 四种常用的实现方法 1.继承Thread. Thread是 ...

  2. 一步一步掌握java的线程机制(一)----创建线程

    现在将1年前写的有关线程的文章再重新看了一遍,发现过去的自己还是照本宣科,毕竟是刚学java的人,就想将java的精髓之一---线程进制掌握到手,还是有点难度.等到自己已经是编程一年级生了,还是无法将 ...

  3. Java并发1——线程创建、启动、生命周期与线程控制

    内容提要: 线程与进程 为什么要使用多线程/进程?线程与进程的区别?线程对比进程的优势?Java中有多进程吗? 线程的创建与启动 线程的创建有哪几种方式?它们之间有什么区别? 线程的生命周期与线程控制 ...

  4. Java的线程机制

    一.Java中实现多线程的两种方式1) 继承Thread类 Thread类包括了包括和创建线程所需的一切东西. Thread 最重要的方法是 run().编写线程程序时须要覆盖 run() 方法,ru ...

  5. Java精选笔记_多线程(创建、生命周期及状态转换、调度、同步、通信)

    线程概述 在应用程序中,不同的程序块是可以同时运行的,这种多个程序块同时运行的现象被称作并发执行. 多线程可以使程序在同一时间内完成很多操作. 多线程就是指一个应用程序中有多条并发执行的线索,每条线索 ...

  6. 深入浅出 Java Concurrency (30): 线程池 part 3 Executor 生命周期[转]

    我们知道线程是有多种执行状态的,同样管理线程的线程池也有多种状态.JVM会在所有线程(非后台daemon线程)全部终止后才退出,为了节省资源和有效释放资源关闭一个线程池就显得很重要.有时候无法正确的关 ...

  7. JAVA中反射机制二

    声明:如需转载请说明地址来源:http://www.cnblogs.com/pony1223 反射二 利用反射创建对象 1.利用反射创建对象,首先我们创建一个类,类里面,我们知道构造函数有默认的构造函 ...

  8. Android(java)学习笔记171:Service生命周期

    1.Service的生命周期         Android中的Service(服务)与Activity不同,它是不能和用户交互,不能自己启动的,运行在后台的程序,如果我们退出应用的时候,Servic ...

  9. JAVA Eclipse的Android的进程和生命周期是什么

    安卓程序的生命周期是不受自己控制的,安卓的程序根据不同的重要性做了一些区分,最重要的进程仅仅在安卓已经崩溃或者卡死的情况下才会终止前台进程.   Activity就是表现层的界面,它有三种常见的状态, ...

随机推荐

  1. 前端特效: 使用CSS生成的闪光照相机效果

    使用纯CSS生成的照相机效果, 相关CSS代码如下: .container { position: absolute; top: 50%; left: 50%; -webkit-transform: ...

  2. Mybatis源码分析之SqlSessionFactory(一)

    简介 MyBatis的前身叫iBatis,本是apache的一个开源项目, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBa ...

  3. android studio中的常用快捷键

    1.Ctrl+Alt+Space 这个类似Eclipse中的Alt+/,实现智能提示功能的 2.Ctrl+Y 删除当前行,Eclipse中是Ctrl+D,伤不起,每次都习惯性的按Ctrl+D,不删,反 ...

  4. Searching for equivalent of FileNotFoundError in Python 2

    I created a class named Options. It works fine but not not with Python 2. And I want it to work on b ...

  5. Percona-XtraBackup系列二:备份恢复

    #在备份较大数据量的时候推荐xtrabackup,这个工具比mysqldump要快很多. 一.Xtrabackup介绍 1,Xtrabackup是什么 Xtrabackup是一个对InnoDB做数据备 ...

  6. Influxdb数据存储

    环境: CentOS6.5_x64 InfluxDB版本:1.1.0 InfluxDB存储引擎看起来很像一个LSM Tree,它包含预写日志和类似存储在LSM Tree中的SSTables只读数据. ...

  7. 新的Blog

    前两天闲着没事把blog弄了下,之前用jekyll折腾好久都不好使,最后还是决定用Hexo了= =.. .题解在两面都会更新 新Blog地址mlz000.github.io,欢迎来踩>_<

  8. 图解Ajax工作原理

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6126542.html Ajax指Asynchronous JavaScript and XML(异步的 Jav ...

  9. 取自ACE中的bit操作宏(转)

    # define ACE_BIT_ENABLED(WORD, BIT) (((WORD) & (BIT)) != ) # define ACE_BIT_DISABLED(WORD, BIT) ...

  10. Selenium如何支持测试Windows application

    很长一段时间大家都支持Selenium是只支持测试Web应用程序的. 纵观Selenium的成长历程,不难解释这个原因.Selenium开始的时候是作为一个Firefox中的插件出现的,而且做得是纯J ...