一。关于终止线程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的更多相关文章

  1. java线程中的sleep/wait/notify/yield/interrupt方法 整理

    java线程中的sleep/wait/notify/yield/interrupt方法 sleep 该方法能够使当前线程休眠一段时间 休眠期间,不释放锁 休眠时间结束之后,进入可执行状态,加入到线程就 ...

  2. java线程中的interrupt,isInterrupt,interrupted方法

    在java的线程Thread类中有三个方法,比较容易混淆,在这里解释一下 (1)interrupt:置线程的中断状态 (2)isInterrupt:线程是否中断 (3)interrupted:返回线程 ...

  3. java线程中的sleep和wait区别

                                                                            面试题:java线程中sleep和wait的区别以及其资 ...

  4. Java 线程的终止-interrupt

    Java线程的终止——interrupt 取消/关闭的场景 我们知道,通过线程的start方法启动一个线程后,线程开始执行run方法,run方法运行结束后线程退出,那为什么还需要结束一个线程呢?有多种 ...

  5. 在Java 线程中返回值的用法

    http://icgemu.iteye.com/blog/467848 在Java 线程中返回值的用法 博客分类: Java Javathread  有时在执行线程中需要在线程中返回一个值:常规中我们 ...

  6. 并发编程——线程中sleep(),yield(),join(),wait(),notify(),notifyAll()区别

    前言 今天简单的讲一讲线程中sleep(),join(),yield(),wait(),notify(),notifyAll()这些方法的使用以及区别. 不过在讲这些方法之前,需要简单的介绍一下锁池和 ...

  7. 停止Java线程,小心interrupt()方法

    来源:http://blog.csdn.net/wxwzy738/article/details/8516253 程序是很简易的.然而,在编程人员面前,多线程呈现出了一组新的难题,如果没有被恰当的解决 ...

  8. Java - 线程Join与interrupt

    Java多线程系列--“基础篇”08之 join() 概要 本章,会对Thread中join()方法进行介绍.涉及到的内容包括:1. join()介绍2. join()源码分析(基于JDK1.7.0_ ...

  9. 为什么JAVA线程中没有Running状态?

    面试官问:为什么 Java 线程没有 Running 状态?我懵了 —— 转  芋道源码 什么是 RUNNABLE? 与传统的ready状态的区别 与传统的running状态的区别 当I/O阻塞时 如 ...

随机推荐

  1. H5 音频标签自定义样式修改以及添加播放控制事件

    说明: 需求要求这个音频标签首先要是可适配移动端浏览器的,音频样式就是参考微信做的. 最终效果如下: 具体实现 思路: H5 的 <audio> 标签是由浏览器负责实现默认样式的.所以不同 ...

  2. angluarjs2入门学习资源

    http://www.runoob.com/angularjs2/angularjs2-tutorial.htmlhttps://segmentfault.com/a/1190000008423981 ...

  3. OpendID是什么?

    一.OpenID的概念 1.问题的提出 2.OpenID是什么? 3.规范演进 二.OpenID 的运行原理 1.参与者 2.运行原理 3.典型场景 4.开源实现 5.优点&缺点 优点:   ...

  4. SpringBoot 概念和起步

    一.概念和由来 1.什么是 Spring Boot Spring Boot 的设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用特定方式来进行配置,从而使开发人员不再需要定义样板化 ...

  5. RxJava系列4(过滤操作符)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  6. jQuery ajax方法success()中后台传来的四种数据类型

    1.后台返回一个页面 js代码 /**(1)用$("#content-wrapper").html(data);显示页面*/ $.ajax({ async : false, cac ...

  7. git初试

    在gitLab上新建一个项目,creat项目文件之后,进入到项目的路径之后,复制命令git clone ‘git@gitlab.touzila.com:xiacaixiang/gitgitTest1. ...

  8. spark2.1:flatMap的用法

    代码示例: val sample_data_combine_result=List( (0,(List(FitModel(4022,1447.92,-8.38983306721434,2.0)),1) ...

  9. 解决 Can't Connect to MySQL Server on IPAddress (10061) 的问题

    我的MySQL服务器安装在Ubuntu 14.04.3 LTS操作系统上. 然后我通过局域网内的另一台电脑连不上,但是能ping通. 解决办法是首先找到my.cnf这个文件. 我的文件位置在/etc/ ...

  10. X5 Blink下文字自动变大

    在X5 Blink中,页面排版时会主动对字体进行放大,会检测页面中的主字体,当某一块的字体在我们的判定规则中,认为字体的字号较小,并且是页面中的主要字体,就会采用主动放大的操作.这显然不是我们想要的. ...