欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解Java编程中线程的挂起、恢复和终止的方法

程序员文章站 2024-03-06 21:52:02
有时,线程的挂起是很有用的。例如,一个独立的线程可以用来显示当日的时间。如果用户不希望用时钟,线程被挂起。在任何情形下,挂起线程是很简单的,一旦挂起,重新启动线程也是一件简...

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

挂起,终止和恢复线程机制在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中挂起、恢复和终止线程

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机制控制线程的更多例子。尽管这种机制不像老方法那样“干净”,然而,它是确保运行时不发生错误的方法。它是所有新的代码必须采用的方法。