欢迎使用CSDN-markdown编辑器

来源:互联网 发布:怎样看出淘宝是包邮的 编辑:程序博客网 时间:2024/05/22 13:52

《Java 线程编程》 学习笔记5

第5章 完美终止线程

5.1 中断线程:interrupt()

  1. 当一个线程运行时,另一个线程可以调用对应的 Thread 对象的 interrupt() 方法来中断它:public void interrupt()
  2. 这个方法只是在目标线程中设置一个标志位,表示它已经被中断,并立即返回。该方法可能抛出 SecurityException,表示发出中断请求的线程没有权限中断其他线程
    • 在 Thread 上调用 checkAccess() 方法可以进行安全性检查,这个方法又会调用 SecurityManager 的 checkAccess(Thread) 方法。

警告:
SecurityException 属于 RuntimeException 的一个子类,因此,对于可能抛出此异常的 Thread 或 ThreadGroup 的任何方法,并不需要 try/catch 块。默认时,应用程序没有定义 SecurityManager。所以,在代码中需要进行一般性检查,使用方法 System.getSecurityManager()。如果返回 null,则表示没有安装 SecurityManager。如果没有返回 null,则调用 SecurityManager 时必须小心。常见覆写 SecurityManager 方法:

import java.io.*;  class PasswordSecurityManager extends SecurityManager {      private String password;      PasswordSecurityManager(String password) {          super();          this.password = password;      }      private boolean accessOK() {          int c;          //DataInputStream dis = new DataInputStream(System.in);          BufferedReader dis = new BufferedReader(new InputStreamReader(System.in));          String response;          System.out.println("What's the secret password?");          try {              response = dis.readLine();              if (response.equals(password))                  return true;              else                  return false;          } catch (IOException e) {              return false;          }      }      public void checkRead(FileDescriptor filedescriptor) {          if (!accessOK())              throw new SecurityException("Not a Chance!");      }      public void checkRead(String filename) {          if (!accessOK())              throw new SecurityException("No Way!");      }      public void checkRead(String filename, Object executionContext) {          if (!accessOK())              throw new SecurityException("Forget It!");      }      public void checkWrite(FileDescriptor filedescriptor) {          if (!accessOK())              throw new SecurityException("Not!");      }      public void checkWrite(String filename) {          if (!accessOK())              throw new SecurityException("Not Even!");      }  }   

5.1.1 中断休眠线程

  1. 代码示例:
public class SleepInterrupt extends Object implements Runnable {    public void run() {        try {            System.out.println("in run - about to sleep for 20 seconds");            Thread.sleep(20000);            System.out.println("in run() - woke up");        } catch(InterruptionException x) {            System.out.println("in run() - interrupted while sleeping");            return;        }        System.out.println("in run() - doing stuff after nap");        System.out.println("in run() - leaving normally");    }    public static void main(String[] args) {        SleepInterrupt si = new SleepInterrupt();        Thread t = new Thread(si);        t.start();        // 确保新线程有机会运行一段时间        try {            Thread.sleep(2000);        }         catch(InterruptedExcepted x) {        }        System.out.println("in main() - interrupting other thread");        t.interrupt();        System.out.println("in main() - leaving");    }}/*运行结果:    in run()  - about to sleep for 20 seconds    in main() - interrupting other thread    in main() - leaving    in run()  - interrupting while sleeping*/

5.1.2 待决中断

  1. 上一个示例说明在线程 sleep() 时,会被 interrupt()。另外,如果在调用 sleep() 之前,中断已经被调用,那它会立即抛出 InterruptedException。
public class PendingInterrupt extends Object {    public static void main(String[] args) {        if(args.length > 0) {            Thread.currentThread().interrupt();        }    }    long startTime = System.currentTimeMillis();    try {        Thread.sleep(2000);        System.out.println("was Not interrupted.");    }    catch (InterruptedException x) {        System.out.println("was interrupted");    }    System.out.println("elapsedTime = " + (System.currentTimeMillis() - startTime));}/*如果不带参数执行:    was Not interrupted    elapsedTime = 2080带参数执行:    was interrupted    elapsedTime = 110*/

5.1.3 使用 isInterrupted()

  1. 可以在 Thread 对象上调用 isInterrupted() 方法来检查任何线程的中断状态。
  2. public boolean isInterrupted()

5.1.4 使用 Thread.interrupted()

  1. 如果线程被中断,调用该函数,将返回 true,同时清除中断标志位。
  2. public static boolean isInterrupted()

5.1.5 InterruptedException

5.2 挂起和恢复线程运行

  1. 加入某个程序使用一个线程按顺序翻转图片达到动画显示的目的,当动画不可见时,就没有必要继续动画显示,直到窗口可见后,再次恢复动画。

5.2.1 使用淘汰的方法 suspend() 和 resume()

技巧:
这些方法和类已经被 Sun 公司淘汰,说明开发人员应该尽量避免使用它们。淘汰的方法仍然可以使用,但是编译代码时,就会发出警告。淘汰这些方法或类,表示他们过时了,或者使用时比较危险,有可能在将来的 JDK 版本中删除。

  1. suspend() 方法是在 JDK 1.2 中淘汰的方法,因为如果在不合适的时候挂起线程(如锁定共享资源时),此时可能会发生死锁条件(deadlock condition)。

5.2.2 在不恰当的时候挂起

  1. 下面的代码示例通过休眠来减缓运行,使线程更可能在不适当的时候被挂起。

5.2.3 不使用淘汰方法实现挂起和恢复

  1. 示例代码:
public class AlternateSuspendResume extends Object implements Runnable {    private volatile int firstVal;    private volatile int secondVal;    private volatile boolean suspended; // 等待状态变量,用于跟踪让内部线程临时终止运行的请求    public boolean areValesEqual() {        return (firstVal == secondVal);    }    public void run() {        try {            suspend = false;            firstVal = 0;            secondVal = 0;            workMethod();        } catch(InterruptedException x) {            System.out.println("interrupted while in workMethod()");        }    }    private void workMethod() throws InterruptedException {        int val = 1;        while(true) {            // 仅当挂起时才运行的代码            waitWhileSuspended();            stepOne(Val);            stepTwo(Val);            val++;            // 仅当挂起时才运行的代码            waitWhileSuspended();            Thread.sleep(200);        }    }    public void suspendRequest() {        suspended = true;    }    public void resumeRequest() {        suspended = false;    }    private void waitWhileSuspended() throws InterruptedException {        // 这是一个『繁忙等待』技术的示例        // 它是非等待条件改变的最佳途径        // 因为它会不断请求处理器周期来检查执行        // 更佳的技术是:使用 Java 内置的『等待-通知』机制        while(suspended) {            Thread.sleep(200);        }    }}

技巧:
如果在代码中有多个安全的地方可以挂起线程,对所有这些安全地方,应该添加更多的 waitWhileSuspended() 方法调用。只要确保没有在持有锁时允许挂起就行了!应该频繁使用 waitWhileSuspended(),有助于线程对挂起请求的快速反应。同时,要记住,调用 waitWhileSuspended() 会耗费一些处理器资源,因此,也不要用得太频繁。

0 0
原创粉丝点击