java stop和waiting_关于java线程中stop interrupt daemon wait notify

一。关于终止线程stop与interrupt

一般来说,线程执行结束后就变成消亡状态,乍看之下我们并不需要人为进行干预(人为停止线程),不过凡事都有例外吧,在服务器或者其他应用场景下,线程为了提供服务而一直在不停的运转,因此必要时刻我们还需“人为干涉的”。

通常情况下,终止线程有两种方式:stop与interrupt

1) stop:暴力的停止线程(不管线程执行到哪段代码,立刻干掉),这个方法因为过于暴力会导致安全问题,因此JDK不推荐使用。

2) interrupt:优雅停止,调用该方法会通知线程可以进行停止操作了,此时线程只是变成可停止状态(thread.isInterrupted的值为true),实际上并没有停止

请看下段代码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.bdqn.lyrk.basic;2

3 /**

4 * 一个线程设置共享变量的值,保持ID与name值相同5 * 另外一个线程读取共享变量的值,发现ID与name值不同时打印6 *7 *@authorchen.nie8 * @date 2018/1/309 **/

10 public classStopThreadUnsafe {11

12 public static User user = newUser();13

14 public static classUser {15 private intid;16 privateString name;17

18 public intgetId() {19 returnid;20 }21

22 public void setId(intid) {23 this.id =id;24 }25

26 publicString getName() {27 returnname;28 }29

30 public voidsetName(String name) {31 this.name =name;32 }33

34 publicUser() {35 id = 0;36 name = "0";37 }38

39 @Override40 publicString toString() {41 return "User [id=" + id + ",name=" + name + "]";42 }43 }44

45 public static class ChangeObjectThread extendsThread {46

47 @Override48 public voidrun() {49 while (true) {50 synchronized(user) {51 if(Thread.currentThread().isInterrupted()) {52 break;53 }54 int i = (int) System.currentTimeMillis() / 1000;55 user.setId(i);56 try{57 Thread.sleep(100);58 } catch(InterruptedException e) {59 Thread.currentThread().interrupt();60 }61 user.setName("" +i);62

63 }64 Thread.yield();65 }66 }67 }68

69 public static class ReadObjectThread extendsThread {70

71 @Override72 public voidrun() {73 while (true) {74 synchronized(user) {75 if (user.getId() !=Integer.parseInt(user.getName())) {76 System.out.println(user);77 }78 }79 Thread.yield();80 }81 }82 }83 }

View Code

Main方法:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.bdqn.lyrk.basic;2

3 public classMain {4 public static void main(String[] args) throwsInterruptedException {5 newStopThreadUnsafe.ReadObjectThread().start();6 while (true) {7 StopThreadUnsafe.ChangeObjectThread thread = newStopThreadUnsafe.ChangeObjectThread();8 thread.start();9 Thread.sleep(200);10 thread.stop();11 //thread.interrupt();

12 }13 }14 }

View Code

此时调用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)

代码如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.bdqn.lyrk.basic;2

3 public classDaemonDemo {4 public static class DaemonT extendsThread {5 @Override6 public voidrun() {7 while (true){8 System.out.println("I am alive");9 try{10 Thread.sleep(1000);11 } catch(InterruptedException e) {12 e.printStackTrace();13 }14 }15 }16 }17

18 public static void main(String[] args) throwsInterruptedException {19 DaemonT daemonT = newDaemonT();20 daemonT.setDaemon(true);21 daemonT.start();22 Thread.sleep(5000);23 }24 }

View Code

运行结果

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方法则唤醒所有在等待队列中的线程

代码示例:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecom.bdqn.lyrk.basic;2

3 public classSimpleWN {4 public static final Object object = newObject();5

6 public static class T1 extendsThread {7

8 @Override9 public voidrun() {10 synchronized(object) {11 System.out.println("开始执行线程...");12 try{13 object.wait();14 } catch(InterruptedException e) {15 e.printStackTrace();16 }17 System.out.println("结束执行线程...");18 }19 }20 }21

22 public static class T2 extendsThread {23 @Override24 public voidrun() {25 synchronized(object) {26 System.out.println("5秒后准备唤醒线程..");27 try{28 Thread.sleep(5000);29 } catch(InterruptedException e) {30 e.printStackTrace();31 }32 object.notify();33 }34 }35 }36

37 public static voidmain(String[] args) {38 T1 t1 = newT1();39 T2 t2 = newT2();40 t1.start();41 t2.start();42 }43 }

View Code

输出内容:

开始执行线程...

5秒后准备唤醒线程..

结束执行线程...

Process finished with exit code 0

注意以下几点:

1)当线程T1被notify过后,也必须要重新获取对象锁,才能够继续执行

2)sleep也能达到wait的效果,但是唯一区别时,sleep时并不会释放对象锁,因此其他线程并没有得到执行的机会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值