前言:
此时姐妹们对“java内功”大体比较着重,小伙伴们都想要学习一些“java内功”的相关知识。那么小编同时在网上收集了一些有关“java内功””的相关知识,希望你们能喜欢,各位老铁们快快来了解一下吧!《射雕英雄传》里有这么个桥段,郭靖自拜江南七怪为师后,刻苦练功,从不懈怠,但是进展缓慢,弄的江南七怪都心灰意冷,觉得他不是练武的材料。后来,全真派掌门丹阳子马钰得知丘处机和江南七怪的赌约,对江南七怪心生敬重,于是特地来到蒙古,在悬崖绝顶教授郭靖全真派内功足足两年,郭靖内功不仅大有长进,练起江南七怪教授的武功也得心应手起来。
全真派内功被誉为天下内功正宗,进境虽慢,却绝不出岔子。而JUC就是如此,JUC是高并发的基石,学好了JUC,就是打好了内功根基,再学习高并发相关知识就有了理论基础。接下来我们聊聊JUC那些事儿。
JUC就是java.util .concurrent工具包的简称,专门用来处理多线程相关问题的。
什么是进程和线程
进程是程序的⼀次执⾏,是系统进⾏资源分配和调度的独⽴单位,每⼀个进程都有它⾃⼰的内存空间和系统资源
在同⼀个进程内⼜可以执⾏多个任务,⽽这每⼀个任务我们就可以看做是⼀个线程
创建线程的三种方式
public void startThead() throws ExecutionException, InterruptedException { //方式一,继承自thread,不推荐 new Thread() { @Override public void run() { log.info("方式1执行"); } }.start(); //方式二,实现Runnable接口,业务与线程分离 new Thread(new Runnable() { @Override public void run() { log.info("方式二执行"); } }).start(); //方式三,使用FutureTask,可以获得线程执行结果 FutureTask<Long> task = new FutureTask<>(new Callable<Long>() { @Override public Long call() throws Exception { Thread.sleep(1000); return 100L; } }); new Thread(task).start(); //获取线程执行结果,处于阻塞状态 log.info(task.get() + "");}
打断线程(interrupt)
很多人对interrupt方法有个误解,以为调用这个方法后线程就不会执行了,其实interrupt方法只会设置打断标记,不会终止线程的执行。如果被打断线程处于sleep,wait,join则会抛出InterruptedException.
sleep情况下被打断,会终止睡眠并抛InterruptedException
public void testInterrupt() throws InterruptedException { Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { //调用interrupt后会抛InterruptedException异常 log.info("被打断"); } log.info("还能继续执行"); } }); thread.start(); TimeUnit.SECONDS.sleep(1); thread.interrupt();}
正常运行的情况下被打断
public void testInterrupt() throws InterruptedException { Thread thread = new Thread(() -> { while (true) { log.info("正在执行"); if (Thread.currentThread().isInterrupted()) { log.info("interrupt方法会让打断标志为true,手动退出"); break; } } }); thread.start(); TimeUnit.SECONDS.sleep(1); thread.interrupt();}
优雅的终止线程
thread里面有个stop方法可以停止线程,但这个方法不会释放锁,而且该方法已经过时了,永远不要靠调这个方法来终止线程。
我们来看个经典的两阶段终止模式
public void testInterrupt() throws InterruptedException { Thread thread = new Thread(() -> { while (true) { if (Thread.currentThread().isInterrupted()) { log.info("线程终止,释放资源"); break; } log.info("执行监控"); try { //睡眠1S TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { log.info("sleep的时候被打断会清除打断标志,需要重新设置"); Thread.currentThread().interrupt(); } } }); thread.start(); TimeUnit.SECONDS.sleep(5); thread.interrupt();}
输出如下:
17:05:02.106 [Thread-0] INFO com.wkt.ThreadTest - 执行监控17:05:03.119 [Thread-0] INFO com.wkt.ThreadTest - 执行监控17:05:04.119 [Thread-0] INFO com.wkt.ThreadTest - 执行监控17:05:05.125 [Thread-0] INFO com.wkt.ThreadTest - 执行监控17:05:06.138 [Thread-0] INFO com.wkt.ThreadTest - 执行监控17:05:07.102 [Thread-0] INFO com.wkt.ThreadTest - sleep的时候被打断不会设置标志位,需要自己设置17:05:07.102 [Thread-0] INFO com.wkt.ThreadTest - 线程终止,释放资源
用户线程与守护线程
Java线程分为用户线程(主线程)和守护线程,线程的daemon属性为true表示是守护线程,false表示是用户线程。
用户线程是系统的工作线程,它会完成这个程序需要完成的业务操作。
守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程。守护线程会在主线程退出后自动终止。设置守护线程,需要在start()方法之前进行
当程序中所有用户线程执行完毕之后,不管守护线程是否结束,系统都会自动退出
标签: #java内功