线程的“结束”
创始人
2024-01-21 05:27:13
0

【一道概率很高的面试题】:

  • 如何优雅的结束一个线程?
    上传一个大文件,正在处理费时的计算,如何优雅的结束这个线程呢?

【stop方法】:

【为何不建议使用stop呢?】:
因为很容易产生数据不一致的问题;
stop方法不管你线程处于什么状态,如果持有很多把锁,它会二话不说释放所有的锁,并且不会做善后的工作。原先的锁如果是为了数据的一致性,那么使用stop有可能就会打破数据的一致性。

 public class T01_Stop {public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("go on");SleepHelper.sleepSeconds(1);}});t.start();SleepHelper.sleepSeconds(5);t.stop();  //不建议大家使用。}
}

在这里插入图片描述

【 suspend_resume 】:

【这两个方法被废掉的原因】:
原因和stop非常的类似 , 万一暂停的瞬间持有一把锁 , 这一把锁是不会被释放的,如果你忘记了恢复,那么就缔造出了一把《永恒的锁》。所以也是会产生数据不一致的问题的。

public class T02_Suspend_Resume {public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("go on");SleepHelper.sleepSeconds(1);}});t.start();SleepHelper.sleepSeconds(5);t.suspend();  //暂停;SleepHelper.sleepSeconds(3);t.resume();  //恢复执行。}
}

【volatile结束线程】:

【不太适合的情况】:
循环中有个数统计的计数器。
循环中有wait、recv、accept等方法,wait会阻塞住,不能进行下一次循环,也无法结束。
【适合的情况】:
不太依赖中间的状态——如上传数据,多上传一些 / 少上传一些 都不影响的这种情况。

public class T03_VolatileFlag {private static volatile boolean running = true;public static void main(String[] args) {Thread t = new Thread(() -> {long i = 0L;while (running) {//wait recv accepti++;}System.out.println("end and i = " + i); //4168806262 4163032200});t.start();SleepHelper.sleepSeconds(1);running = false;}
}

【interrupt结束线程】:

//interrupt比volatile更加优雅一些 , 因为如果是volatile的话 , 中间有一些wait / sleep 的话 , 你是停不了的 , 无法跳到下一次循环。但如果是interrupt的话,你只要在sleep / wait 里面处理 InterruptedException 也可以正确的结束这个线程。
【仍有缺点】:
10个元素的容器 , 精确到第5个 , 这个也是无法达到的!!!
【这种情况如何正常结束呢?】:
必须生产者Thread和外面打断它的Thread , 两者配合才可以。
【其他方法】:
内部线程进行定时的检查 , 每隔多长时间检查一次标志位 , 每经过一次循环检查一次标志位。

/*** interrupt是设定标志位*/
public class T04_Interrupt_and_NormalThread {public static void main(String[] args) {Thread t = new Thread(() -> {while (!Thread.interrupted()) {   //只要标记位没被设置,我就一直循环~ ~ ~//sleep wait}System.out.println("t1 end!");});t.start();SleepHelper.sleepSeconds(3);t.interrupt();}
}
public class T05_InterruptAndPark {public static void main(String[] args) {Thread t = new Thread(() -> {System.out.println("1");LockSupport.park();System.out.println("2");});t.start();SleepHelper.sleepSeconds(2);t.interrupt();}
}

【阶段总结】:

【volatile 和 interrupt】:
总之,你不依赖于中间精确的次数和精确的时间的话 , 它俩都行。

【结束线程的方法】:

  1. 自然结束(能自然结束就尽量自然结束)
  2. stop() suspend() resume()
  3. volatile标志
    1. 不适合某些场景(比如还没有同步的时候,线程做了阻塞操作,没有办法循环回去)
    2. 打断时间也不是特别精确,比如一个阻塞容器,容量为5的时候结束生产者,
      但是,由于volatile同步线程标志位的时间控制不是很精确,有可能生产者还继续生产一段儿时间
  4. interrupt() and isInterrupted(比较优雅)

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...