// 以编程的方式控制线程,在实际编程中,一般是在受控制的线程中定义一个标志变量,其他线程通过改变标志变量的值,来控制线程的暂停
// 恢复运行及自然终止,以下Test15类就是一个可以被控制的线程,状态包括 SUSP 暂停, STOP 终止,RUN 运行
// Test15类继承于ControlledThread类,因此Test15类是受控制的线程,在Test15类的run方法的while循环中,每次循环
// 结束前都会调用checkState()方法,判断接下来到底是继续运行,还是暂停或者终止运行
// 主线程通过调用Test15对象的setStat()方法来控制Test15线程,当实例变量的count值大于5时,就让Test15线程暂停,把Test15
// 对象的实例变量count设为0,然后再使Test15线程恢复运行,主线程最后终止Test15线程的运行
// ThreadGroup类表示线程组,他能够对一组线程进行集中管理,在创建一个线程对象时,可以通过构造方法指定它所属的线程组 Thread(ThreadGroup group, String name)
// 在构造线程组的实例时,也可以显示指定父亲线程组,例如:ThreadGroup(ThreadGroup group, String name)
// ThreadGroup类的activeCount()方法返回当前活着的线程,enumerate(Thread[] tarray) 方法把当前活着的线程的引用拷贝到参数tarray中
// 问题,假如在执行group.activeCount()方法时有5个活着的线程,那么activeCount的值为5,但是当执行group.enumerate(machines)方法时已经有6个活着的线程,那么enumerate()
// 方法只会向machines数组中存放5个线程的引用,还有一个线程被忽略,所以不推荐使用ThreadGroup类,这个类还有一个有用的功能是uncaughtException()方法
// 处理线程未捕获的异常:如果当前线程没有捕获异常,那么java虚拟机会寻找相关的UncaughtExceptionHandler实例,如果找到,就调用他的uncaughtException(Thread t, Throwable e)方法
// 在Thread类中提供了一个公共的静态的UncaughtExceptionHandler内部接口,他负责处理线程未捕获的异常,接口完整名是Thread.UncaughtExceptionHandler,他的唯一方法是
// uncaughtException(Thread t,Throwable e)参数t表示抛出异常的线程,参数e表示具体的异常
// Thread类中提供了两个设置异常处理类的方法
// setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
// setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
// 第一个方法是静态方法,设置线程类的默认异常处理器,第二个方法是实例方法,设置线程实例的当前异常处理器
// ThreadGroup实现了Thread.UncaughtExceptionHandler接口,当一个线程实例抛出未捕获的异常时,java首先查找线程实例的当前异常处理器,没有找到,就会找实例所属的线程组作为异常处理器,都是调用
// uncaughtException()方法,还是没有则调用当前线程类的默认异常处理器,最后,就把来自方法调用堆栈的异常信息打印到标准输出流System.err中
// 恢复运行及自然终止,以下Test15类就是一个可以被控制的线程,状态包括 SUSP 暂停, STOP 终止,RUN 运行
// Test15类继承于ControlledThread类,因此Test15类是受控制的线程,在Test15类的run方法的while循环中,每次循环
// 结束前都会调用checkState()方法,判断接下来到底是继续运行,还是暂停或者终止运行
// 主线程通过调用Test15对象的setStat()方法来控制Test15线程,当实例变量的count值大于5时,就让Test15线程暂停,把Test15
// 对象的实例变量count设为0,然后再使Test15线程恢复运行,主线程最后终止Test15线程的运行
// ThreadGroup类表示线程组,他能够对一组线程进行集中管理,在创建一个线程对象时,可以通过构造方法指定它所属的线程组 Thread(ThreadGroup group, String name)
// 在构造线程组的实例时,也可以显示指定父亲线程组,例如:ThreadGroup(ThreadGroup group, String name)
// ThreadGroup类的activeCount()方法返回当前活着的线程,enumerate(Thread[] tarray) 方法把当前活着的线程的引用拷贝到参数tarray中
// 问题,假如在执行group.activeCount()方法时有5个活着的线程,那么activeCount的值为5,但是当执行group.enumerate(machines)方法时已经有6个活着的线程,那么enumerate()
// 方法只会向machines数组中存放5个线程的引用,还有一个线程被忽略,所以不推荐使用ThreadGroup类,这个类还有一个有用的功能是uncaughtException()方法
// 处理线程未捕获的异常:如果当前线程没有捕获异常,那么java虚拟机会寻找相关的UncaughtExceptionHandler实例,如果找到,就调用他的uncaughtException(Thread t, Throwable e)方法
// 在Thread类中提供了一个公共的静态的UncaughtExceptionHandler内部接口,他负责处理线程未捕获的异常,接口完整名是Thread.UncaughtExceptionHandler,他的唯一方法是
// uncaughtException(Thread t,Throwable e)参数t表示抛出异常的线程,参数e表示具体的异常
// Thread类中提供了两个设置异常处理类的方法
// setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
// setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
// 第一个方法是静态方法,设置线程类的默认异常处理器,第二个方法是实例方法,设置线程实例的当前异常处理器
// ThreadGroup实现了Thread.UncaughtExceptionHandler接口,当一个线程实例抛出未捕获的异常时,java首先查找线程实例的当前异常处理器,没有找到,就会找实例所属的线程组作为异常处理器,都是调用
// uncaughtException()方法,还是没有则调用当前线程类的默认异常处理器,最后,就把来自方法调用堆栈的异常信息打印到标准输出流System.err中
// ThreadLocal类:这个类用来存放线程的局部变量,每个线程都有单独的局部变量,彼此之间不会共享,ThreadLocal<T>类主要包括以下三个方法:
class ControlledThread extends Thread{
public static final int SUSP = 1;
public static final int STOP = 2;
public static final int RUN = 0;
private int state = RUN;
public synchronized void setStat(int state){
this.state = state;
if(state == RUN){
notify();
}
}
public synchronized boolean checkStat() {
while (state == SUSP) {
try {
System.out.println(Thread.currentThread().getName() + ":wait");
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (state == STOP) {
return false;
}
return true;
}
}
public class Test15 extends ControlledThread{
private int count;
public void run(){
// 循环判断Test15的checkStat()是否进入终止状态,返回true就一直运行下去
while(true){
synchronized (this) {
count++;
System.out.println(Thread.currentThread().getName()+":run " + count+ " times");
}
if(!checkStat()){
System.out.println(Thread.currentThread().getName()+":stop");
break;
}
}
}
public synchronized int getCount(){return count;}
public synchronized void reset(){count=0;System.out.println(Thread.currentThread().getName()+":reset");}
public static void main(String[] args) {
Test15 test15 = new Test15();
// 启动test15线程
test15.start();
// for 循环200次
for(int i = 0;i<200;i++){
// 由于test15线程运行了一段时间后,将CPU使用权让给主线程,主线程判断count的值是否大于5,大于5就进入暂停状态,此时test15获得了CPU使用权,state == SUSP此时进入等待状态
// 主线程运行reset方法将count值重新设置为0,将ControlledThread.RUN设置为运行状态,主线程中的for循环次数等于200时,则设置test15线程为停止状态
if(test15.getCount()>5){
test15.setStat(ControlledThread.SUSP);
yield();
test15.reset();
test15.setStat(ControlledThread.RUN);
}
yield();
}
test15.setStat(ControlledThread.STOP);
}
}
// (自定义)异常处理
class MichineHandler implements Thread.UncaughtExceptionHandler{
@Override
public void uncaughtException(Thread t, Throwable e) {
}
}
// 线程组默认实现了Thread.UncaughtExceptionHandler,所以可以设置线程组的异常处理
class MichineGroup extends ThreadGroup{
public MichineGroup() {
super("MichineGroup");
}
@Override
public void uncaughtException(Thread t, Throwable e) {
// TODO Auto-generated method stub
super.uncaughtException(t, e);
}
}