线程的挂起,继续执行和停止

有时挂起一个执行的线程是十分有用的.例如,一个单独的线程可以用于显示一天中的时间,如果用户不需要时钟,那么该线程就应该挂起.无论情况怎样,挂起线程都是件简单的事情.挂起后,重新启动也很简单.
从Java2开始,挂起,停止和继续执行线程的机制与早期java版本不尽相同.在Java2以前,程序送由Thread定义的suspend(),resume()和stop()来暂停,重新启动和停止线程的执行.他的形式如下所示:
final void resume()
final void suspend()
final void stop()
尽管这些方法对于管理线程的执行看似非常合理方便,但是现在不能再使用他们.原因如下:thread类的suspend()方法已经被java2摒弃了,因为他有时会导致与死锁有关的严重的系统错误.此外,Java2也摒弃了resume()方法,虽然他不会产生什么问题,但是使用他必须使用suspend()方法.java2还摒弃了Thread类的stop方法,因为该方法有时也会导致严重的系统错误.
因为现在无法使用suspend(),resume()或stop()方法来控制线程,所以你可能首先会想到,这样就无法来暂停,重启或终止线程了.然而,幸运的是,事实并非如此.线程的设计必须有一个run()方法来周期性的检查他,以确定该线程是否应该挂起,继续执行或停止执行.通常,这是依靠两个标志变量来完成的,一个用于挂起和继续执行,另一个用于停止.对于挂起和继续执行,只要标志变灵设置为”running”,那么run()方法必须继续让线程执行.如果标志变量设置成”susoend”,那么线程必须暂停.对于停止标志而言,如果设置他为”stop”,那么线程必须终止.
下面的程序演示了实现自己的suspend().resume()和stop()版本的方法:
public class test2
{
    // @param args
    public static void main(String args[])
    {
     MyThread ob1 = new MyThread("My Thread");
     
     try {
         Thread.sleep(1000);
         
         ob1.mysuspend();
         System.out.println("suspending thread");
         Thread.sleep(1000);
         
         ob1.myresume();
         System.out.println("myresuming thread");
         Thread.sleep(1000);
         
         ob1.mysuspend();
         System.out.println("suspending thread");
         Thread.sleep(1000);
         
         ob1.myresume();
         System.out.println("myresuming thread");
         Thread.sleep(1000);
         
         ob1.mysuspend();
         System.out.println("stopping thread");
         ob1.mystop();
         
     }catch(InterruptedException exc) {
         System.out.println("Main thread  Interruped");
     }
     
     try {
         ob1.thrd.join();
     }catch(InterruptedException e) {
         System.out.println("main thread  interruped");
     }
     System.out.println("Main thread exiting");
    }
}
class MyThread implements Runnable
{
    Thread thrd;
    boolean suspended;
    boolean stoped;
    
    MyThread(String name)
    {
        thrd = new Thread(this,name);
        stoped = suspended = false;
        thrd.start();
    }
    
    public void run()
    {
        System.out.println(thrd.getName()+"  starting.");
        try {
            for(int i=1;i<1000;i++)
            {
                System.out.print(i+" ");
                if(i%10 == 0)
                {
                    System.out.println();
                    Thread.sleep(250);
                }
                
                synchronized(this)
                {
                    while(suspended) wait();
                    if(stoped) break;
                }
            }
        }catch(InterruptedException exc) {
            System.out.println(thrd.getName()+"interruped");
        }
        System.out.println(thrd.getName()+"  exiting");
    }
    
    synchronized void mystop()
    {
        stoped = true;
        suspended = false;
        notify();
    }
    
    synchronized void mysuspend()
    {
        suspended = true;
    }
    
    synchronized void myresume()
    {
        suspended = false;
        notify();
    }
}
程序输出如下所示:
My Thread starting.
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
suspending thread
41 myresuming thread
42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
suspending thread
81 myresuming thread
82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
121 stopping thread
My Thread exiting
Main thread exiting
程序的工作原理如下:线程类MyThread定义了两个布尔型变量suspedned和stopped,他们用于监督线程的挂起和终止.构造函数将他们两个都初始化为false,run()方法包含可以检查suspended的同步代码块.如果该变量为true,那么调用wait()方法挂起线程的执行,而这就需要调用将suspended设为false的myresume(),然后再调用notify()来重新启动线程.
停止线程需要调用将stoped设置为true的mystop().此外,mystop()还可以设置suspended为false,然后调用notify().这些步骤都是终止一个挂起的线程所必须的.
问:多线程看起来是改进程序效率的有效方法,你能给我一些高效使用多线程的提示吗?
答:高效使用多线程的关键就是采用并行方式而不是串行方式进行思考.例如,当程序中有两个完全独立的子系统时,可以让他们使用独立线程.但是需要注意,如果创建的线程太多,就会降低程序的性能而不是增强性能.记住系统开销与线程间的切换有关.如果创建的线程太多,就会有更多的CPU时间用于线程的切换而不是执行程序.