错误的线程停止方式-stop
产生的问题
stop()会真正杀死线程,如果这时候线程锁住了共享资源,线程被杀死后再也没有机会去释放锁资源,其它线程将永远不会获得锁System.exit(int)停止线程,会让整个程序停止。。
interrupt 两阶段终止模式优雅的停止线程
指的就是当希望结束一个线程的时候,送出一个终止请求,但是不会马上停止,做一些刷新工作。进入“终止处理中”,在该状态下,不会进行该线程日常工作任务的操作,而是进行一些终止操作。
public class RightStopThreadWithSleepEveryLoop {
private Thread monitor;
public static void main(String[] args) throws InterruptedException {
RightStopThreadWithSleepEveryLoop rightStopThreadWithSleepEveryLoop = new RightStopThreadWithSleepEveryLoop();
// 主线程运行
rightStopThreadWithSleepEveryLoop.start();
Thread.sleep(10);
rightStopThreadWithSleepEveryLoop.stop();
}
private void start() {
monitor = new Thread(){
@Override
public void run() {
while (true) {
Thread thread = Thread.currentThread();
if (thread.isInterrupted()) {
System.out.println("执行资源释放");
break;
}
try {
// 休息两秒在监控
Thread.sleep(3);
System.out.println("执行周期操作");
} catch (InterruptedException e) {
e.printStackTrace();
// 在睡眠中收到终止请求
thread.interrupt();
}
}}
};
monitor.start();
}
private void stop() {
monitor.interrupt();
}
}
细节:
- isInterrupted() : 不会清除打断标记
- Interrupted() : 会清除打断标记。
interrupt 影响 park 线程
LockSupport.park() 方法 阻塞执行线程
public class ParkThreadStopTest {
private static void test() throws InterruptedException {
Thread thread = new Thread(() -> {
System.out.println("park....");
LockSupport.park();
System.out.println("unpark.........");
System.out.println("打断状态 : " + Thread.currentThread().isInterrupted());
}, "t1");
thread.start();
// 让主线程 睡 1 秒
Thread.sleep(1000);
thread.interrupt();
}
public static void main(String[] args) throws InterruptedException {
test();
}
}
在 Thread.currentThread().isInterrupted() 之后,在 执行 park 不会产生之前的阻塞。中单标记位还在。
执行 Thread.interrupted 会产生与之前相同的阻塞。中断标记位消除,不中断,继续阻塞。
不推荐使用的方法
容易破坏同步代码块,不推荐使用。 都过时啦
- stop() : 停止线程运行
interrupted来停止 - suspend() : 挂起线程 wait
- resume() : 恢复线程运行 notify
守护线程
只要其他非守护线程执行结束,即使守护线程的代码没有执行玩,也会强制结束 在线程start前调用
setDaemon(true)方法。 最常见的守护线程:gc线程
线程状态
- 新建状态:该线程被创建,但没有和操作系统相关联(在Java中表现为未调用start() 方法)
- 可运行状态; 该线程已经被创建(与操作系统线程相关联)、可以由CPU调度执行。
- 运行状态:获取了CPU时间片运行的状态。
- cpu 时间片用完,从运行状态转换到可运行状态,发生上下文切换
- 阻塞状态:线程实际不会用到cpu、会导致线程上下文切换。IO阻塞操作
- 等待状态
- 计时等待状态
- 终止状态:线程已经执行完毕,生命周期结束了,不会再转换为其他形态。
统筹规划 泡茶问题
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "洗茶壶");
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "烧开水");
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "lw");
Thread t2 = new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + "洗茶杯");
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "拿茶叶");
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "洗茶杯");
TimeUnit.SECONDS.sleep(2);
t1.join();
System.out.println(Thread.currentThread().getName() + "泡茶");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "xw");
t1.start();
t2.start();
}
上述代码 只能实现
xw等待lw的执行结果,不能时lw等待xw的执行完毕,代码最好能适应两种情况。
模拟不了lw将 水壶 交给xw泡茶、或者说是xw把 茶叶 交给lw泡茶。