热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ThreadRunnable线程及stop()、interrupt()、sleep()等方法讲解

如何开启线程开启线程2种方式:自定义类继承Thread类,重写run方法;new自定义类().start()自定义类实现Runnab
  • 如何开启线程

开启线程2种方式:

自定义类继承Thread类,重写run方法;new 自定义类().start()

自定义类实现Runnable接口,实现run方法;new Thread(new 自定义类()).start()

  • Thread和Runable

Thread是对线程的抽象封装,完成独立完成某个任务的调度,包括任务的开始、暂停、结束等操作。本身是实现Runnable接口,所以具有Runnable的所有功能。

Runnable 是对任务的抽象封装,业务任务的具体逻辑封装。本身不具有独立资源调度。需要Thread协助完成,这也就是前面说的开启线程需要先new Thread() 通过参数把Runnable传递进去。

  • JVM开启,默认开启哪些线程(JDK1.8为例)

public static void main(String[] args) {//虚拟机线程系统的管理接口(JVM开启的线程);对JVM系统进行监控时,使用类ManagementFactoryThreadMXBean threadMXBean= ManagementFactory.getThreadMXBean();ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);for(ThreadInfo threadInfo:threadInfos){System.out.println("["+threadInfo.getThreadId()+"]"+threadInfo.getThreadName());}/* 一般项目启动会启动的线程有:* [8]JDWP Command Reader[7]JDWP Event Helper Thread[6]JDWP Transport Listener: dt_socket[5]Attach Listener[4]Signal Dispatcher[3]Finalizer 线程管理Object finalize()方法,每个对象销毁时都会调用这个方法;不推荐在这个方法中写资源释放,有时调用不到(main结束这个线程也就没有了)[2]Reference Handler[1]main 主线程,线程关闭其他线程会依次关闭* */}

  • stop/interrupt/sleep等方法总结

stop():结束线程,比较野蛮会立即结束线程。比如当前线程正在写一个文件,或者正在写入数据库,正在完成一半任务时,接到stop命令,立即线程结束,导致文件不完整,错误的文件或数据库数据不完整等问题。所以JDK1.8之后不在推荐使用。当然如果能够保证当前线程没有这些类似任务,采用stop停止线程也是可以的。

interrupt():标记线程状态为中断状态(线程本身并不会结束),此时线程中如果有join、wait、sleep等方法调用的时候会抛出异常java.lang.InterruptedException。在线程的run()方法中我们需要自己写逻辑结束线程。isInterrupt()可获取线程的中断状态。Thread.interrupt()静态方法内部会调用当前线程的isinterrupt()方法,但是内部也会再次把状态标志位修改,所有一般都是用实例interrupt方法。对于Runnable实例化的线程,一般用Thread.currentThread().interrupt() 方法判断。

sleep():使当前线程进入阻塞状态。同时这个方法内部会监测interrupt状态,如果当前线程中断后,同时线程还睡眠时,会报异常java.lang.InterruptedException: sleep interrupted。sleep()并不会释放对象锁,只有锁代码块执行完后,其他线程才能够获取锁

  • 线程stop方法案例

import java.util.concurrent.TimeUnit;/*** @ClassName xu01* @Description des* @Author zyk* @Date 2019/9/24* @Version 1.0**/
public class xu01 {private static class UseThread extends Thread{@Overridepublic void run() {while(true) {System.out.println("正在写入文件,写入部分...");}}}public static void main(String[] args) {UseThread useThread=new UseThread();useThread.start();//main线程睡眠20try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}//main线程2秒后关闭// 1:stop() 是一个@Deprecated不推荐使用,过于野蛮停止线程(会出现线程写部分文件就挂了)useThread.stop();System.out.println("main 线程结束");}
}

  • 线程interrupt方法案例

import java.util.concurrent.TimeUnit;/*** @ClassName xu01* @Description des* @Author zyk* @Date 2019/9/24* @Version 1.0**/
public class xu01 {private static class UseThread extends Thread{@Overridepublic void run() {while(true) {System.out.println("正在写入文件,写入部分...");//判断线程状态是否,是否需要结束// if(isInterrupted()){//Thread.interrupted静态方法也是同样的功能,内部会获取当前线程if(Thread.interrupted()){System.out.println("线程状态:"+interrupted());System.out.println("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");break;}}}}public static void main(String[] args) {UseThread useThread=new UseThread();useThread.start();//main线程睡眠20try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}//main线程2秒后关闭//只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束useThread.interrupt();System.out.println("main 线程结束");}
}

  • 线程sleep方法案例

在线程中添加sleep睡眠逻辑,做完一件事后睡眠一段时间,再次做事情。

import java.util.concurrent.TimeUnit;/*** @ClassName xu01* @Description des* @Author zyk* @Date 2019/9/24* @Version 1.0**/
public class xu01 {private static class UseThread extends Thread{@Overridepublic void run() {while(true) {System.out.println("正在做某件任务...");System.out.println("结束一段任务后,线程睡眠一段时间");try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}if(Thread.interrupted()){System.out.println("线程状态:"+interrupted());System.out.println("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");break;}}}}public static void main(String[] args) {UseThread useThread=new UseThread();useThread.start();//main线程睡眠20try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}//main线程2秒后关闭//只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束useThread.interrupt();System.out.println("main 线程结束");}
}

注意:这样线程并不会结束,运行结果如下

正在做某件任务...
结束一段任务后,线程睡眠一段时间
java.lang.InterruptedException: sleep interruptedat java.lang.Thread.sleep(Native Method)at java.lang.Thread.sleep(Thread.java:340)at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)at controller.multithread.xu01$UseThread.run(xu01.java:21)
main 线程结束
正在做某件任务...
结束一段任务后,线程睡眠一段时间
正在做某件任务...
结束一段任务后,线程睡眠一段时间

这是因为 TimeUnit.MILLISECONDS.sleep(20);会抛出异常后,把当前线程中断状态又改回去了,导致线程还会继续执行。

需要修改代码:第一种方式,在sleep方法上添加try-catch,在InterruptedException异常代码块中再次调用interrupte()方法。第二种方式,把while死循环监视起来,出现InterruptedException 异常后结束线程,修改后代码如下:

import java.util.concurrent.TimeUnit;/*** @ClassName xu01* @Description des* @Author zyk* @Date 2019/9/24* @Version 1.0**/
public class xu01 {private static class UseThread extends Thread{@Overridepublic void run() {try {while (true) {System.out.println("正在做某件任务...");System.out.println("结束一段任务后,线程睡眠一段时间");try {TimeUnit.MILLISECONDS.sleep(20);//java.lang.InterruptedException: sleep interrupted 需要把这个异常抛出去} catch (InterruptedException e) {//interrupt();throw e;}if (Thread.interrupted()) {System.out.println("线程状态:" + interrupted());System.out.println("判断当前文件写完了,然后结束线程,不会导致文件是个损坏的文件");break;}}}catch (InterruptedException e){e.printStackTrace();System.out.println("子线程结束");}}}public static void main(String[] args) {UseThread useThread=new UseThread();useThread.start();//main线程睡眠20try {TimeUnit.MILLISECONDS.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}//main线程2秒后关闭//只是标记线程标志位为中断状态,需要在run方法中写逻辑结束线程,否则线程还是不能够结束useThread.interrupt();System.out.println("main 线程结束");}
}

  • 线程池使用

JDK1.8不在推荐使用Executors创建线程了,推荐使用ThreadPoolExecutor,可控制最大线程数量。而Executors 最多创建线程数量是 Integer.MAX_VALUE 会导致系统OOM问题

public static void main(String[] args) throws ExecutionException, InterruptedException {int count=230;//线程池1:ExecutorService pool1=Executors.newCachedThreadPool();ExecutorService pool2=Executors.newFixedThreadPool(5);//线程池2:ThreadFactory namedThreadFactory=new ThreadFactoryBuilder().setNameFormat("jake-pool-%d").build();ExecutorService pool=new ThreadPoolExecutor(5,200,60L,TimeUnit.SECONDS,new LinkedBlockingQueue(1024),namedThreadFactory,new ThreadPoolExecutor.AbortPolicy());for(int i=0;i{System.out.println("========线程名称:"+Thread.currentThread().getName());});}pool.shutdown();System.out.println("shutdown");}

 


推荐阅读
author-avatar
手机用户2502880041
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有