JUC(一)--天下内功正宗

《射雕英雄传》里有这么个桥段,郭靖自拜江南七怪为师后,刻苦练功,从不懈怠,但是进展缓慢,弄的江南七怪都心灰意冷,觉得他不是练武的材料。后来,全真派掌门丹阳子马钰得知丘处机和江南七怪的赌约,对江南七怪心生敬重,于是特地来到蒙古,在悬崖绝顶教授郭靖全真派内功足足两年,郭靖内功不仅大有长进,练起江南七怪教授的武功也得心应手起来。

全真派内功被誉为天下内功正宗,进境虽慢,却绝不出岔子。而JUC就是如此,JUC是高并发的基石,学好了JUC,就是打好了内功根基,再学习高并发相关知识就有了理论基础。接下来我们聊聊JUC那些事儿。

JUC就是java.util .concurrent工具包的简称,专门用来处理多线程相关问题的。

什么是进程和线程

进程是程序的⼀次执⾏,是系统进⾏资源分配和调度的独⽴单位,每⼀个进程都有它⾃⼰的内存空间和系统资源

在同⼀个进程内⼜可以执⾏多个任务,⽽这每⼀个任务我们就可以看做是⼀个线程

创建线程的三种方式

public void startThead() throws ExecutionException, InterruptedException {//方式一,继承自thread,不推荐new Thread() {@Overridepublic void run() {log.info("方式1执行");}}.start();//方式二,实现Runnable接口,业务与线程分离new Thread(new Runnable() {@Overridepublic void run() {log.info("方式二执行");}}).start();//方式三,使用FutureTask,可以获得线程执行结果FutureTask task = new FutureTask<>(new Callable() {@Overridepublic 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() {@Overridepublic 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 {//睡眠1STimeUnit.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()方法之前进行

当程序中所有用户线程执行完毕之后,不管守护线程是否结束,系统都会自动退出


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部