欢迎使用CSDN-markdown编辑器
来源:互联网 发布:怎样看出淘宝是包邮的 编辑:程序博客网 时间:2024/05/22 13:52
《Java 线程编程》 学习笔记5
第5章 完美终止线程
5.1 中断线程:interrupt()
- 当一个线程运行时,另一个线程可以调用对应的 Thread 对象的 interrupt() 方法来中断它:
public void interrupt()
- 这个方法只是在目标线程中设置一个标志位,表示它已经被中断,并立即返回。该方法可能抛出 SecurityException,表示发出中断请求的线程没有权限中断其他线程。
- 在 Thread 上调用
checkAccess()
方法可以进行安全性检查,这个方法又会调用 SecurityManager 的checkAccess(Thread)
方法。
- 在 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 中断休眠线程
- 代码示例:
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 待决中断
- 上一个示例说明在线程 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()
- 可以在 Thread 对象上调用 isInterrupted() 方法来检查任何线程的中断状态。
public boolean isInterrupted()
5.1.4 使用 Thread.interrupted()
- 如果线程被中断,调用该函数,将返回 true,同时清除中断标志位。
public static boolean isInterrupted()
5.1.5 InterruptedException
5.2 挂起和恢复线程运行
- 加入某个程序使用一个线程按顺序翻转图片达到动画显示的目的,当动画不可见时,就没有必要继续动画显示,直到窗口可见后,再次恢复动画。
5.2.1 使用淘汰的方法 suspend() 和 resume()
技巧:
这些方法和类已经被 Sun 公司淘汰,说明开发人员应该尽量避免使用它们。淘汰的方法仍然可以使用,但是编译代码时,就会发出警告。淘汰这些方法或类,表示他们过时了,或者使用时比较危险,有可能在将来的 JDK 版本中删除。
suspend()
方法是在 JDK 1.2 中淘汰的方法,因为如果在不合适的时候挂起线程(如锁定共享资源时),此时可能会发生死锁条件(deadlock condition)。
5.2.2 在不恰当的时候挂起
- 下面的代码示例通过休眠来减缓运行,使线程更可能在不适当的时候被挂起。
5.2.3 不使用淘汰方法实现挂起和恢复
- 示例代码:
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
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- 欢迎使用CSDN-markdown编辑器
- JavaScript函数绑定
- Redis数据类型之String类型
- 二分查找
- Cocos2d-过渡篇(三) 触摸机制
- 爬取糗事百科文字段子,(2016年10月22日可用)
- 欢迎使用CSDN-markdown编辑器
- dfs找环
- 欢迎加入我们的iOS开发交流群
- 编辑距离(动态规划法)
- ionic-app.js分析
- 笔记:TRULY_SPINACH(优酷播单:3D坦克大战实例)
- Java 基于TCP的Socket网络编程的入门及示例
- Uestc381 - Knight and Rook
- Array.filter(function(x){})