一。关于终止线程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. 关于Android 7.0(API24)相机的问题汇总

    在开发Android项目的时候,我们会用到相机,有些时候只是开发一个普通的扫码,仅仅赋予一下 权限 就好了,但是有些时候是需要拍照和从相册中获取照片的.我们在Android 5.0以及5.0之前调用相 ...

  2. 一个诚实的孩纸选Python的原因

    我之所以会选择python语言程序设计这门课,是因为我一开始预选选的选修课都没选上,然后在补选的时候,在别人选剩的课里面选择了python. 上了两节课之后,我发现python还挺有意思的,挺喜欢py ...

  3. Oracle 使用pl/sql将表中的数据读出到文件中

    (1)在服务器上创建文件路径及文件 [oracle@redhat errormsg]$ touch test01.txt (2)在数据库中创建路径及授权 (3)创建存储过程 CREATE OR REP ...

  4. 以太坊挖矿源码:clique算法

    上文我们总结了以太坊最主要的共识算法:ethash算法,本文将重点分析以太坊的另一个共识算法:clique. 关键字:clique,共识算法,puppeth,以太坊地址原理,区块校验,认证结点,POA ...

  5. Docker学习笔记 - Docker Compose

    一.概念 Docker Compose 用于定义运行使用多个容器的应用,可以一条命令启动应用(多个容器). 使用Docker Compose 的步骤: 定义容器 Dockerfile 定义应用的各个服 ...

  6. 单点登录实现机制:web-sso

    参考链接,感谢作者:https://zm10.sm-tc.cn/?src=l4uLj8XQ0IiIiNGckZ2TkJiM0ZyQktCZlo2Mi5uNmp6S0I/QysrJyszPztGXi5K ...

  7. 新概念英语(1-a)句子集锦

  8. maven的使用之一简单的安装

    首先,我们知道,在传统的项目中,我们会导入一堆的jar包,那样的话,我们会发现我们的jar包的大小已经占了整个项目大小的90%以上,甚至更多,而且,我们的jar包只能自己使用,如果 其他人想用的话,还 ...

  9. leetcode算法:Island Perimeter

    You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represen ...

  10. LayUI之table数据表格获取行、行高亮等相关操作

    前言 目前LayUI数据表格既美观有不乏一些实用功能.基本上表格应有的操作已经具备,LayUI作者[贤心]肯定是煞费苦心去优化,此处致敬.但是实话实话,如果单纯那数据表格功能来说,EasUI的数据表格 ...