虽说Thread类提供了stop()和suspend()方法,但这两种方法过于粗暴,如果线程占用了一些资源(如打开了一个文件,建立了一个数据库连接什么的),直接stop()或是suspend()是会产生问题的。
要终止Thread,最好的方法就是让run()方法正常运行完毕,不过有的run()方法里面直接是一个while (true),这时就要使用一些特殊的手段。
1. 使用中断
基本思想就是在run()方法中的while (true)里检查线程是否中断,如果中断就退出(当然,退出之前可以做一些关闭资源的操作);这么一来在主线程中就可以调用Thread.interrupt()来中断线程,进而使线程退出。
public class Runner3 implements Runnable {
@Override
public void run() {
while(true) {
System.out.println(new Date());
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < 1000) {
// 不使用Thread.sleep(1000)
// 使用while来消耗一秒钟时间
}
if (Thread.currentThread().isInterrupted()) { // 时刻检查该线程是否中断
// 或者使用 if (Thread.interrupted()) {
return; // 如果线程中断就退出
}
}
}
}
public class MultiThreadTest3 {
public static void main(String[] args) {
Runner3 r = new Runner3();
Thread t = new Thread(r);
t.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// do nothing
}
t.interrupt(); // 中断Thread t,使run()方法退出,线程结束
}
}
如果在run()方法中的while (true)里有可能导致InterruptedException的操作,那么退出run()方法的代码可以放在catch语句里。
public class Runner2 implements Runnable {
@Override
public void run() {
while(true) {
System.out.println(new Date());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return; // 发生中断异常时,线程直接退出
}
}
}
}
public class MultiThreadTest2 {
public static void main(String[] args) {
Runner2 r = new Runner2();
Thread t = new Thread(r);
t.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// do nothing
}
t.interrupt(); // 中断Thread t,使t.sleep()时产生中断异常,进而终止线程
}
}
2. 使用标志位
使用标志位boolean flag,将run()方法中的while (true)改为while (flag)(轮询标志位),主线程中就就可以通过修改flag来退出线程。
public class Runner4 implements Runnable {
private boolean flag = true;
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
while(flag) {
System.out.println(new Date());
long time = System.currentTimeMillis();
while (System.currentTimeMillis() - time < 1000) {
// 不使用Thread.sleep(1000)
// 使用while来消耗一秒钟时间
}
}
}
}
public class MultiThreadTest4 {
public static void main(String[] args) {
Runner4 r = new Runner4();
Thread t = new Thread(r);
t.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// do nothing
}
r.setFlag(false); // 设置标志位,使run()方法退出,线程结束
}
}
这个方法有一个缺点:如果while (flag) {...}方法阻塞了,则flag的设置会失效。
3. 最好的方法是使用线程池
当线程不用了,就让它sleep并放进队列中,这样可以最大限度地利用资源。不过这暂时不在本文的讨论范围内。
2010-10-04 补充:
注意这里说的退出是这样的一种情况:主线程(比如说 main 方法)创建了一个 Thread t,然后想在主线程中使t退出。
文章一开始说的 stop()、suspend() 方法的问题是:主线程一句 t.stop() 或是 t.suspend() 就了事了,t 在 run() 方法中没有机会去关闭资源,不像中断或是轮询标志位的方法中,t 在 run() 方法里还握有一点主动权
2011-11-03 补充:
方法2可以使用的一个优化步骤是将标志位设置为 volatile
分享到:
相关推荐
WM_CANCELJOURNAL(0x004B):取消某些类型的消息。 WM_NOTIFY(0x004E):控件发送此消息给其父窗口,当控件自身发生某些事情或用户与控件交互时。 WM_INPUTLANGCHANGEREQUEST(0x0050):输入语言改变请求。 WM_...
### Java与Android编程中的专业颜色代码 在Java与Android开发过程中,颜色的选择和定义是非常重要的一个环节。良好的颜色设计不仅能提升应用的用户体验,还能更好地传达应用程序的品牌形象和风格。本文将根据提供的...
本问题主要涉及的是HEX颜色代码,它是Web开发中最常用的颜色表示方法。 HEX颜色代码是由六个十六进制数字组成,前两个代表红色分量,中间两个代表绿色分量,最后两个代表蓝色分量。每个分量的取值范围从00(最小,...
- **`static void Main(string[] args)`**:这是C#程序的入口点,所有的控制台应用程序都必须有一个`Main`方法。 综上所述,这些示例代码涵盖了WPF界面设计的基本元素,如文本显示、密码输入及基本的字符串处理等...
#### WM_CANCELJOURNAL (0x004B) 取消日志记录时发送,对于需要跟踪用户操作的应用程序非常重要。 #### WM_NOTIFY (0x004E) 控件向父窗口发送通知时发送,携带了`NMHDR`结构体,提供了控件ID、控件类型和通知码。 ...
Jun 22 00:50:19 localhost CROND[21181]: (lujun9972) MAIL (mailed 102 bytes of output but got status0x004b#012) ``` 这表明邮件发送失败。 接下来,检查`mail`服务的日志,通常位于`/var/log/maillog`。在...
- **用途**:用于同步多个线程的队列。 #### WM_GETMINMAXINFO – 获取最小/最大信息 - **值**:`0x0024` - **用途**:获取窗口最小化和最大化时的尺寸信息。 #### WM_PAINTICON – 绘制图标 - **值**:`0x0026` -...
NlsLexicons004b
NlsData004b
- 发送命令`0x00C7`设置VCOM偏移,并发送参数`0x004B`。 - 发送命令`0x00EB`使能GVDD,并发送参数`0x0001`。 - **内部时钟设置**: - 发送命令`0x00B1`设置内部时钟,并发送相关参数`0x0006`和`0x001C`。 - **...
- `19200` 对应 `004B` - `38400` 对应 `0096` - `57600` 对应 `00E1` 通过将这些十六进制代码写入指定的位置,即可完成通信速率的修改。 ### 四、执行程序 文件中还提到了一个名为 `Navione.exe` 的程序,这应该...
SDSS计算研究Python作业作业#004b逻辑运算符(总计14) 目标: 评估布尔逻辑语句有时您可能需要检查多个条件。 一种选择是将if语句嵌套在if语句中,但是您也可以使用运算符检查条件语句打开名为example1.py的文件,...
作业#004b逻辑运算符(总计14) 目标: 评估布尔逻辑语句 有时您可能需要检查多个条件。 一种选择是将if语句嵌套在if语句中,但是您也可以使用运算符检查条件语句 打开名为example1.py的文件,以查看“和”运算符...
0x0010 004b 05d0 0000 7f11 3310 0a02 1615 ca67 .K......3......g 0x0020 1844 eee6 0035 0037 daef 0003 0100 0001 .D...5.7........ 0x0030 0000 0000 0000 0377 7777 0473 6f68 7503 .......www.sohu. 0x0040 ...
- **注意事项**:此消息发出后程序将立即终止。 #### WM_QUERYOPEN($0013) - **含义**:查询窗口是否可以打开。 - **应用场景**:在打开窗口之前检查是否符合条件。 - **注意事项**:有助于避免不必要的窗口打开...
- **作用**:终止应用程序的消息循环。 - **应用场景**:在所有必要的清理工作完成后退出程序。 #### WM_QUERYOPEN($0013) - **定义**:当窗口正在打开或关闭时发送。 - **作用**:询问应用程序是否可以安全地...
- **DH-ITACD-004B**:与抓拍相机配套使用,用于检测车辆的到达和离开,从而触发相机进行抓拍。 #### 7. 技术参数与接口说明 - **DH-ITC102-GVRB3A技术参数**:包括分辨率、帧率、网络接口等。 - **DH-ITC215-GVRB...
SDSS计算研究Python作业作业#004b的循环(总计成绩15) 目标: 新变量类型:元组使用for循环遍历元组的成员使用for循环遍历整数序列可以用来跳过并继续迭代使用break从for循环退出当您要重复一段代码一定次数时,...
SDSS计算研究Python作业作业#004b的循环(总计成绩15) 目标: 新变量类型:元组使用for循环遍历元组的成员使用for循环遍历整数序列可以用来跳过并继续迭代使用break从for循环退出当您要重复一段代码一定次数时,...