有时,线程的挂起是很有用的。例如,一个独立的线程可以用来显示当日的时间。如果用户不希望用时钟,线程被挂起。在任何情形下,挂起线程是很简单的,一旦挂起,重新启动线程也是一件简单的事。

挂起,终止和恢复线程机制在Java 2和早期版本中有所不同。尽管你运用Java 2的途径编写代码,你仍需了解这些操作在早期Java环境下是如何完成的。例如,你也许需要更新或维护老的代码。你也需要了解为什么Java 2会有这样的变化。因为这些原因,下面内容描述了执行线程控制的原始方法,接着是Java 2的方法。

Java 1.1或更早版本的线程的挂起、恢复和终止

先于Java2的版本,程序用Thread 定义的suspend() 和 resume() 来暂停和再启动线程。它们的形式如下:
    final void suspend( )
    final void resume( )
下面的程序描述了这些方法:

 // Using suspend() and resume().
class NewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.t.suspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.t.resume();
System.out.println("Resuming thread One");
ob2.t.suspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
ob2.t.resume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}

程序的部分输出如下:

 New thread: Thread[One,5,main]
One: 15
New thread: Thread[Two,5,main]
Two: 15
One: 14
Two: 14
One: 13
Two: 13
One: 12
Two: 12
One: 11
Two: 11
Suspending thread One
Two: 10
Two: 9
Two: 8
Two: 7
Two: 6
Resuming thread One
Suspending thread Two
One: 10
One: 9
One: 8
One: 7
One: 6
Resuming thread Two
Waiting for threads to finish.
Two: 5
One: 5
Two: 4
One: 4
Two: 3
One: 3
Two: 2
One: 2
Two: 1
One: 1
Two exiting.
One exiting.
Main thread exiting.

Thread类同样定义了stop() 来终止线程。它的形式如下:

void stop( )
一旦线程被终止,它不能被resume() 恢复继续运行。

Java 2中挂起、恢复和终止线程

Thread定义的suspend(),resume()和stop()方法看起来是管理线程的完美的和方便的方法,它们不能用于新Java版本的程序。下面是其中的原因。Thread类的suspend()方法在Java2中不被赞成,因为suspend()有时会造成严重的系统故障。假定对关键的数据结构的一个线程被锁定的情况,如果该线程在那里挂起,这些锁定的线程并没有放弃对资源的控制。其他的等待这些资源的线程可能死锁。

Resume()方法同样不被赞同。它不引起问题,但不能离开suspend()方法而独立使用。Thread类的stop()方法同样在Java 2中受到反对。这是因为该方法可能导致严重的系统故障。设想一个线程正在写一个精密的重要的数据结构且仅完成一个零头。如果该线程在此刻终止,则数据结构可能会停留在崩溃状态。

因为在Java 2中不能使用suspend(),resume()和stop() 方法来控制线程,你也许会想那就没有办法来停止,恢复和结束线程。其实不然。相反,线程必须被设计以使run() 方法定期检查以来判定线程是否应该被挂起,恢复或终止它自己的执行。有代表性的,这由建立一个指示线程状态的标志变量来完成。只要该标志设为“running”,run()方法必须继续让线程执行。如果标志为“suspend”,线程必须暂停。若设为“stop”,线程必须终止。

当然,编写这样的代码有很多方法,但中心主题对所有的程序应该是相同的。

下面的例题阐述了从Object继承的wait()和notify()方法怎样控制线程的执行。该例与前面讲过的程序很像。然而,不被赞同的方法都没有用到。让我们思考程序的执行。

NewTread 类包含了用来控制线程执行的布尔型的实例变量suspendFlag。它被构造函数初始化为false。Run()方法包含一个监测suspendFlag 的同步声明的块。如果变量是true,wait()方法被调用以挂起线程。Mysuspend()方法设置suspendFlag为true。Myresume()方法设置suspendFlag为false并且调用notify()方法来唤起线程。最后,main()方法被修改以调用mysuspend()和myresume()方法。

 // Suspending and resuming a thread for Java2
class NewThread implements Runnable {
String name; // name of thread
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
suspendFlag = false;
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
while(suspendFlag) {
wait();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
suspendFlag = true;
}
synchronized void myresume() {
suspendFlag = false;
notify();
}
}
class SuspendResume {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
try {
Thread.sleep(1000);
ob1.mysuspend();
System.out.println("Suspending thread One");
Thread.sleep(1000);
ob1.myresume();
System.out.println("Resuming thread One");
ob2.mysuspend();
System.out.println("Suspending thread Two");
Thread.sleep(1000);
ob2.myresume();
System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}

该程序的输出与前面的程序相同。此书的后面部分,你将看到用Java 2机制控制线程的更多例子。尽管这种机制不像老方法那样“干净”,然而,它是确保运行时不发生错误的方法。它是所有新的代码必须采用的方法。

系列文章:

Java知多少(65)线程的挂起、恢复和终止的更多相关文章

  1. Java知多少(56)线程模型

    Java运行系统在很多方面依赖于线程,所有的类库设计都考虑到多线程.实际上,Java使用线程来使整个环境异步.这有利于通过防止CPU循环的浪费来减少无效部分. 为更好的理解多线程环境的优势可以将它与它 ...

  2. Java知多少(57)主线程

    当Java程序启动时,一个线程立刻运行,该线程通常叫做程序的主线程(main thread),因为它是程序开始时就执行的.主线程的重要性体现在两方面: 它是产生其他子线程的线程: 通常它必须最后完成执 ...

  3. Java知多少(58)线程Runnable接口和Thread类详解

    大多数情况,通过实例化一个Thread对象来创建一个线程.Java定义了两种方式: 实现Runnable 接口: 可以继承Thread类. 下面的两小节依次介绍了每一种方式. 实现Runnable接口 ...

  4. Java知多少(61)线程优先级

    线程优先级被线程调度用来判定何时每个线程允许运行.理论上,优先级高的线程比优先级低的线程获得更多的CPU时间.实际上,线程获得的CPU时间通常由包括优先级在内的多个因素决定(例如,一个实行多任务处理的 ...

  5. Java知多少(62)线程同步

    当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一刻仅被一个线程占用.达到此目的的过程叫做同步(synchronization).像你所看到的,Java为此提供了独特的,语言水平上的 ...

  6. Java知多少(63)线程间通信

    上述例题无条件的阻塞了其他线程异步访问某个方法.Java对象中隐式管程的应用是很强大的,但是你可以通过进程间通信达到更微妙的境界.这在Java中是尤为简单的. 像前面所讨论过的,多线程通过把任务分成离 ...

  7. java并发编程(三)线程挂起,恢复和终止的正确方法

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17095733    下面我们给出不用上述两个方法来实现线程挂起和恢复的策略--设置标志位. ...

  8. java线程技术6_线程的挂起和唤醒[转]

    转自:http://blog.chinaunix.net/uid-122937-id-215913.html 1. 线程的挂起和唤醒      挂起实际上是让线程进入“非可执行”状态下,在这个状态下C ...

  9. JAVA并发实现三(线程的挂起和恢复)

    package com.subject01; /** * 通过标识位,实现线程的挂起和回复 * com.subject01.AlternateSuspendResume.java * @author ...

随机推荐

  1. 生产环境中tomcat的配置

    生产环境中要以daemon方式运行tomcat 通常在开发环境中,我们使用$CATALINA_HOME/bin/startup.sh来启动tomcat, 使用$CATALINA_HOME/bin/sh ...

  2. c#基础在winform操作数据库,实现增删改查

    1.数据库操作类代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; us ...

  3. linux VIM 下的语法高亮及自动缩进

    显示行号 set number 自动缩进有两个选项 set autoindent set cindent autoindent 就是自动缩进的意思,当你在输入状态用回车键插入一个新行,或者在 norm ...

  4. Editplus中添加System.out.println()快捷键

    首先,找到自己电脑Editplus的安装路径,在所属文件夹中找到JAVA.ACP文件: 然后,在文件的末尾加上如下代码: #T=syso System.out.println("^!&quo ...

  5. Syntax error , insert “EnumBody” to complete EnumDeclaration

    当@Test写在方法前面的时候因为没有导入junit的jar包,如果已经导入架包依然是同样的错误,那就是方法没写对,或者还没有写方法

  6. unity3d 脚本周期函数

    1,编辑器阶段 Reset方法:当脚本第一次添加到游戏对象或执行Reset命令时会调用Reset方法,常用来初始化脚本的各个属性: 2,场景第一次加载阶段 Awake方法:在Start方法之前调用: ...

  7. Android Studio 使用过程遇到的坑

    最近在尝试Android Studio打Jar的包,然而事实并不是想象的那么简单,so,写多个坑的解决,以备不时之需. 1.Error:Execution failed for task ':app: ...

  8. ecshop 添加后台页面以及设置权限

    转自 http://blog.csdn.net/tgh1981/article/details/10394059 ecshop 添加新页面 给ecshop后台增加管理功能页面 比如我们增加一个统计报表 ...

  9. 转:甲骨文发布大数据解决方案 含最新版NoSQL数据库

    原文出处: http://www.searchdatabase.com.cn/showcontent_88247.htm 以下是部分节选: 最新发布的大数据创新成果包括: Oracle Big Dat ...

  10. JavaScript 空间分析库——JSTS和Turf【转】

    https://blog.csdn.net/neimeng0/article/details/80363468 前言 项目中有管线的空间拓扑关系查询需求,在npm中检索到JSTS和Turf两个Java ...