关于java线程中stop interrupt daemon wait notify
一。关于终止线程stop与interrupt
一般来说,线程执行结束后就变成消亡状态,乍看之下我们并不需要人为进行干预(人为停止线程),不过凡事都有例外吧,在服务器或者其他应用场景下,线程为了提供服务而一直在不停的运转,因此必要时刻我们还需“人为干涉的”。
通常情况下,终止线程有两种方式:stop与interrupt
1) stop:暴力的停止线程(不管线程执行到哪段代码,立刻干掉),这个方法因为过于暴力会导致安全问题,因此JDK不推荐使用。
2) interrupt:优雅停止,调用该方法会通知线程可以进行停止操作了,此时线程只是变成可停止状态(thread.isInterrupted的值为true),实际上并没有停止
请看下段代码:
- package com.bdqn.lyrk.basic;
- /**
- * 一个线程设置共享变量的值,保持ID与name值相同
- * 另外一个线程读取共享变量的值,发现ID与name值不同时打印
- *
- * @author chen.nie
- * @date 2018/1/30
- **/
- public class StopThreadUnsafe {
- public static User user = new User();
- public static class User {
- private int id;
- private String name;
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public User() {
- id = 0;
- name = "0";
- }
- @Override
- public String toString() {
- return "User [id=" + id + ",name=" + name + "]";
- }
- }
- public static class ChangeObjectThread extends Thread {
- @Override
- public void run() {
- while (true) {
- synchronized (user) {
- if (Thread.currentThread().isInterrupted()) {
- break;
- }
- int i = (int) System.currentTimeMillis() / 1000;
- user.setId(i);
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- user.setName("" + i);
- }
- Thread.yield();
- }
- }
- }
- public static class ReadObjectThread extends Thread {
- @Override
- public void run() {
- while (true) {
- synchronized (user) {
- if (user.getId() != Integer.parseInt(user.getName())) {
- System.out.println(user);
- }
- }
- Thread.yield();
- }
- }
- }
- }
Main方法:
- package com.bdqn.lyrk.basic;
- public class Main {
- public static void main(String[] args) throws InterruptedException {
- new StopThreadUnsafe.ReadObjectThread().start();
- while (true) {
- StopThreadUnsafe.ChangeObjectThread thread = new StopThreadUnsafe.ChangeObjectThread();
- thread.start();
- Thread.sleep(200);
- thread.stop();
- // thread.interrupt();
- }
- }
- }
此时调用stop终止线程时,得到如下结果
- User [id=1197577,name=1197576]
- User [id=1197577,name=1197576]
- User [id=1197577,name=1197576]
- User [id=1197577,name=1197576]
- User [id=1197578,name=1197577]
原因很简单:stop方法会释放对象锁,并终止线程,当线程还没有与name赋值时,已经被干掉了因此其他线程在读取时,很有可能读到NAME与ID值不一致的情况
二。守护线程Daemon
守护线程顾名思义,是系统的守护者,这个线程为系统的运行默默提供服务,当系统任务运行完毕,守护线程也就完成使命了,比如说垃圾回收线程,JIT线程都是守护线程,设置守护线程的方式:在调用start方法前,通过线程对象.setDaemon(true)
代码如下:
- package com.bdqn.lyrk.basic;
- public class DaemonDemo {
- public static class DaemonT extends Thread {
- @Override
- public void run() {
- while (true){
- System.out.println("I am alive");
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- public static void main(String[] args) throws InterruptedException {
- DaemonT daemonT = new DaemonT();
- daemonT.setDaemon(true);
- daemonT.start();
- Thread.sleep(5000);
- }
- }
运行结果
- I am alive
- I am alive
- I am alive
- I am alive
- I am alive
- Process finished with exit code 0
我们可以看到,当主线程执行完毕后,守护线程也随之结束
三。wait与notify
wait与notify是多线程协同工作的最基本手段,可是这两个方法属于Object的方法,当需要使用wait和notify时,必须配合synchronized使用,此时调用wait方法,当前线程会进入等待队列并释放当前的对象锁,直到线程被唤醒(notify),notify方法会随机唤醒一个在等待队列中的线程,notifyAll方法则唤醒所有在等待队列中的线程
代码示例:
- package com.bdqn.lyrk.basic;
- public class SimpleWN {
- public static final Object object = new Object();
- public static class T1 extends Thread {
- @Override
- public void run() {
- synchronized (object) {
- System.out.println("开始执行线程...");
- try {
- object.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("结束执行线程...");
- }
- }
- }
- public static class T2 extends Thread {
- @Override
- public void run() {
- synchronized (object) {
- System.out.println("5秒后准备唤醒线程..");
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- object.notify();
- }
- }
- }
- public static void main(String[] args) {
- T1 t1 = new T1();
- T2 t2 = new T2();
- t1.start();
- t2.start();
- }
- }
输出内容:
- 开始执行线程...
- 5秒后准备唤醒线程..
- 结束执行线程...
- Process finished with exit code 0
注意以下几点:
1)当线程T1被notify过后,也必须要重新获取对象锁,才能够继续执行
2)sleep也能达到wait的效果,但是唯一区别时,sleep时并不会释放对象锁,因此其他线程并没有得到执行的机会
关于java线程中stop interrupt daemon wait notify的更多相关文章
- java线程中的sleep/wait/notify/yield/interrupt方法 整理
java线程中的sleep/wait/notify/yield/interrupt方法 sleep 该方法能够使当前线程休眠一段时间 休眠期间,不释放锁 休眠时间结束之后,进入可执行状态,加入到线程就 ...
- java线程中的interrupt,isInterrupt,interrupted方法
在java的线程Thread类中有三个方法,比较容易混淆,在这里解释一下 (1)interrupt:置线程的中断状态 (2)isInterrupt:线程是否中断 (3)interrupted:返回线程 ...
- java线程中的sleep和wait区别
面试题:java线程中sleep和wait的区别以及其资 ...
- Java 线程的终止-interrupt
Java线程的终止——interrupt 取消/关闭的场景 我们知道,通过线程的start方法启动一个线程后,线程开始执行run方法,run方法运行结束后线程退出,那为什么还需要结束一个线程呢?有多种 ...
- 在Java 线程中返回值的用法
http://icgemu.iteye.com/blog/467848 在Java 线程中返回值的用法 博客分类: Java Javathread 有时在执行线程中需要在线程中返回一个值:常规中我们 ...
- 并发编程——线程中sleep(),yield(),join(),wait(),notify(),notifyAll()区别
前言 今天简单的讲一讲线程中sleep(),join(),yield(),wait(),notify(),notifyAll()这些方法的使用以及区别. 不过在讲这些方法之前,需要简单的介绍一下锁池和 ...
- 停止Java线程,小心interrupt()方法
来源:http://blog.csdn.net/wxwzy738/article/details/8516253 程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决 ...
- Java - 线程Join与interrupt
Java多线程系列--“基础篇”08之 join() 概要 本章,会对Thread中join()方法进行介绍.涉及到的内容包括:1. join()介绍2. join()源码分析(基于JDK1.7.0_ ...
- 为什么JAVA线程中没有Running状态?
面试官问:为什么 Java 线程没有 Running 状态?我懵了 —— 转 芋道源码 什么是 RUNNABLE? 与传统的ready状态的区别 与传统的running状态的区别 当I/O阻塞时 如 ...
随机推荐
- Struts2之配置
Struts2的默认配置文件是struts.xml放在/web-inf/classes目录下,struts配置文件的最大作用就是配置Action与请求之间的对应关系,并配置逻辑视图名和物理视图名之间的 ...
- LR录制脚本的时候打不开浏览器问题
使用Chrome时,显示开始录制但是Action中无任何脚本,即脚本没成功生成. 使用Firefox(最新版),一直关闭程序,详细信息有StackHash_0a9e. 使用IE11时,也是显示开始录制 ...
- map的infowindow的show事件(ArcGIS API for JS)
- jupyter notebook下python2和python3共存(Ubuntu)
提示NOTICE 时间:2018/04/06 主题:Ubuntu 下CAFFE框架 主角:Jupyter Notebook 简介: Jupyter Notebook(此前被称为 IPython not ...
- ASP.NET CORE 自定义视图组件(ViewComponent)注意事项
*红色字体为固定命名,蓝色为一般命名规则,黄色为ASP.NET CORE 默认查找文件名 概要:1.简单ViewComponent的用法 2.ViewComponent控制器返回值 3.注意事项 1 ...
- SiteMesh在项目中的配置
SiteMesh在项目中的配置 首先在web.xml里面增加siteMesh的配置: <filter> <filter-name>sitemesh</filter-nam ...
- 新概念英语(1-135)The latest report
Lesson 135 The latest report 最新消息 Listen to the tape then answer this question. Is Karen Marsh going ...
- codeforces round 425 div2
A. Sasha and Sticks 水题,判断一下次数的奇和偶就可以的. B. Petya and Exam 赛上的时候没有写出来,orz,记录一下吧. 题意:给出一个模式串,可能会有?和*两种符 ...
- 28.C++- 单例类模板(详解)
单例类 描述 指在整个系统生命期中,一个类最多只能有一个实例(instance)存在,使得该实例的唯一性(实例是指一个对象指针) , 比如:统计在线人数 在单例类里,又分为了懒汉式和饿汉式,它们的区 ...
- Scale
Scale刻度组件. 当你希望用户输入某个范围内的一个数值,使用scale组件可以很好的代替Entry组件. 用法: 创建一个指定范围的Scale组件其实非常容易,你只需要指定from和to两个选项即 ...