澳门新萄京网址Thread源码剖析,风箱树花

【出处】广州部队《常用中草药手册》

[“

【拼音名】Fēnɡ Xiānɡ Shù Huā

\n 前言\n

\n

\n 昨天已经写了:\n

\n

  • \n \n
    多线程\n\n
    三分钟就可以入个门了!\n

\n

\n 如果没看的同学建议先去阅读一遍哦~\n

\n

\n 在写\n \n
文章\n\n
之前通读了一遍《Java 核心技术 卷一》的并发章节和《Java\n \n
并发编程\n\n
实战》前面的部分,回顾了一下以前写过的笔记。从今天开始进入多\n \n
线程\n\n
的知识点咯~\n

\n

\n
我其实也是相当于从零开始学多线程的,如果文章有错的地方还请大家多多包含,不吝在评论区下指正呢~~\n

\n

【来源】为茜草科植物风箱树的花序。夏季采集,晒干。

\n 一、Thread线程类\n \n API\n\n

\n

\n 声明本文使用的是JDK1.8\n

\n

\n 实现多线程从\n \n
本质\n\n
上都是由Thread类来进行操作的~我们来看看Thread类一些\n \n
重要的知识点\n
\n 。Thread这个类很大,不可能整个把它看下来,只能\n
\n 看一些常见的、重要的方法\n \n 。\n

\n

\n 顶部\n \n
注释\n\n
的我们已经\n \n
解析\n\n
过了,如果不知道的同学可前往: 多线程三分钟就可以入个门了!\n

\n

【性味】苦,凉。

\n 1.1设置线程名\n

\n

\n 我们在使用多线程的时候,想要查看线程名是很简单的,调用\n
\n Thread.currentThread().getName()\n\n 即可。\n

\n

\n 如果没有做什么的设置,我们会发现线程的名字是这样子的:\n \n
主线程叫做main,其他线程是Thread-x\n
\n

\n

\n 下面我就带着大家来看看它是怎么命名的:\n

\n

\n
澳门新萄京网址 1\n

\n

\n \n nextThreadNum()\n\n 的方法实现是这样的:\n

\n

\n
澳门新萄京网址 2\n

\n

\n 基于这么一个变量–>\n \n 线程初始化的数量\n \n

\n

\n
澳门新萄京网址 3\n

\n

\n

\n 点进去看到init方法就可以确定了:\n

\n
\n
澳门新萄京网址 4\n

\n

\n 看到这里,如果我们想要为线程起个名字,那也是很简单的。\n \n
Thread给我们提供了构造方法\n
\n !\n

\n

\n
澳门新萄京网址 5\n

\n

\n 下面我们来\n \n
测试\n\n
一下:\n

\n

  • \n 实现了Runnable的方式来实现多线程:\n

\n

public class MyThread implements Runnable {\n    \n    @Override\n    public void run() {\n        // 打印出当前线程的名字\n        System.out.println(Thread.currentThread().getName());\n    }\n}

\n

\n 测试:\n

\n

public class MyThreadDemo {\n    public static void main(String[] args) {\n\n\n        MyThread myThread = new MyThread();\n\n        //带参构造方法给线程起名字\n        Thread thread1 = new Thread(myThread, \"关注公众号Java3y\");\n        Thread thread2 = new Thread(myThread, \"qq群:742919422\");\n\n\n        thread1.start();\n        thread2.start();\n        \n        // 打印当前线程的名字\n        System.out.println(Thread.currentThread().getName());\n    }\n}

\n

\n 结果:\n

\n

\n
澳门新萄京网址 6\n

\n

\n 当然了,我们还可以通过\n \n setName(String name)\n\n
的方法来改掉线程的名字的。我们来看看方法实现;\n

\n

\n
澳门新萄京网址 7\n

\n

\n 检查是否有权限修改:\n

\n

\n
澳门新萄京网址 8\n

\n

\n 至于threadStatus这个状态属性,\n \n
貌似没发现他会在哪里修改\n
\n :\n

\n

\n
澳门新萄京网址 9\n

\n

【功能主治】清热利湿,收敛止泻。治腹泻,痢疾。

\n 1.2守护线程\n

\n

\n 守护线程是\n \n 为其他线程服务的\n \n

\n

  • \n \n \n
    垃圾回收\n\n
    线程就是守护线程\n
    \n ~\n

\n

\n 守护线程有一个\n \n 特点\n \n :\n

\n

  • \n
    当别的用户线程执行完了,虚拟机就会退出,守护线程也就会被停止掉了。\n
  • \n 也就是说:守护线程作为一个\n \n
    服务线程,没有服务对象就没有必要继续运行\n
    \n 了\n

\n

\n 使用线程的时候要注意的地方\n

\n

  1. \n \n 在线程启动前\n \n 设置为守护线程,方法是\n
    \n setDaemon(boolean on)\n\n
  2. \n 使用守护线程\n \n 不要访问共享资源\n \n (\n \n
    数据库\n\n
    、文件等),因为它可能会在任何时候就挂掉了。\n
  3. \n 守护线程中产生的新线程也是守护线程\n

\n

\n 测试一波:\n

\n

public class MyThreadDemo {\n    public static void main(String[] args) {\n\n\n        MyThread myThread = new MyThread();\n\n        //带参构造方法给线程起名字\n        Thread thread1 = new Thread(myThread, \"关注公众号Java3y\");\n        Thread thread2 = new Thread(myThread, \"qq群:742919422\");\n\n        // 设置为守护线程\n        thread2.setDaemon(true);\n\n        thread1.start();\n        thread2.start();\n        System.out.println(Thread.currentThread().getName());\n    }\n}

\n

\n 上面的\n \n
代码\n\n
运行多次可以出现(电脑性能足够好的同学可能测试不出来):\n \n
线程1和主线程执行完了,我们的守护线程就不执行了\n
\n ~\n

\n

\n
澳门新萄京网址 10\n

\n

\n 原理:这也就为什么我们要在\n \n 启动之前\n \n
设置守护线程了。\n

\n

\n
澳门新萄京网址 11\n

\n

【用法用量】内服:煎汤,15~20个。

\n 1.3优先级线程\n

\n

\n 线程优先级高仅仅表示线程\n \n 获取的CPU\n \n
时间\n\n
片的几率高\n
\n ,但这不是一个\n \n 确定的因素\n \n !\n

\n

\n 线程的优先级是\n \n 高度依赖于\n \n
操作系统\n\n
的\n
\n ,Windows和Linux就有所区别(Linux下优先级可能就被忽略了)~\n

\n

\n 可以看到的是,Java提供的优先级默认是5,最低是1,最高是10:\n

\n

\n
澳门新萄京网址 12\n

\n

\n 实现:\n

\n

\n
澳门新萄京网址 13\n

\n

\n \n setPriority0\n\n 是一个本地(navite)的方法:\n

\n

 private native void setPriority0(int newPriority);

\n

【摘录】《*辞典》

\n 1.4线程\n \n 生命\n\n 周期\n

\n

\n
在上一篇介绍的时候其实也提过了线程的线程有3个基本状态:执行、就绪、阻塞\n

\n

\n 在Java中我们就有了这个图,Thread上很多的方法都是\n \n
用来切换线程的状态\n
\n 的,这一部分是重点!\n

\n

\n
澳门新萄京网址 14\n

\n

\n 其实上面这个图是不够完整的,\n \n 省略\n \n
掉了一些东西。后面在讲解的线程状态的时候我会重新画一个~\n

\n

\n 下面就来讲解与线程生命周期相关的方法~\n

\n

\n 1.4.1sleep方法\n

\n

\n 调用sleep方法会进入计时等待状态,等时间到了,\n \n
进入的是就绪状态而并非是运行状态\n
\n !\n

\n

\n
澳门新萄京网址 15\n

\n

\n 于是乎,我们的图就可以补充成这样:\n

\n

\n
澳门新萄京网址 16\n

\n

\n 1.4.2yield方法\n

\n

\n 调用yield方法会先\n \n 让别的线程执行\n \n ,但是\n \n
不确保真正让出\n
\n

\n

  • \澳门新萄京网址,n 意思是:\n \n 我有空,可以的话,让你们先执行\n \n

\n

\n
澳门新萄京网址 17\n

\n

\n 于是乎,我们的图就可以补充成这样:\n

\n

\n
澳门新萄京网址 18\n

\n

\n 1.4.3join方法\n

\n

\n 调用join方法,会等待\n \n 该线程\n \n 执行\n \n
完毕后才执行别的线程\n
\n ~\n

\n

\n
澳门新萄京网址 19\n

\n

\n 我们进去看看\n \n 具体的实现\n \n :\n

\n

\n
澳门新萄京网址 20\n

\n

\n wait方法是在Object上定义的,它是native本地方法,所以就看不了了:\n

\n

\n
澳门新萄京网址 21\n

\n

\n wait方法实际上它也是\n \n 计时等待(如果带时间\n \n
参数\n\n
)\n
\n 的一种!,于是我们可以补充我们的图:\n

\n

\n
澳门新萄京网址 22\n

\n

\n 1.4.3interrupt方法\n

\n

\n 线程中断在之前的版本有stop方法,但是被设置过时了。现在已经\n \n
没有强制线程终止\n
\n 的方法了!\n

\n

\n 由于stop方法可以让\n \n 一个线程A终止掉另一个线程B\n \n

\n

  • \n 被终止的线程B会立即释放\n \n
    锁\n\n
    ,这可能会让\n \n 对象处于不一致的状态\n \n 。\n
  • \n \n 线程A也不知道线程B什么时候能够被终止掉\n \n
    ,万一线程B还处理运行计算阶段,线程A调用stop方法将线程B终止,那就很无辜了~\n

\n

\n 总而言之,Stop方法太暴力了,不\n \n
安全\n\n
,所以被设置过时了。\n

\n

\n 我们一般使用的是interrupt来\n \n 请求终止线程\n \n ~\n

\n

  • \n 要注意的是:interrupt**不会真正停止\n \n
    一个线程,它仅仅是给这个线程发了一个\n
    \n
    信号*告诉它,它应该要结束了(明白这一点非常重要!)\n
  • \n 也就是说:Java设计者实际上是\n \n 想线程自己来终止\n \n
    ,通过上面的\n \n 信号\n \n ,就可以判断处理什么业务了。\n
  • \n 具体到底中断还是继续运行,应该\n \n
    由被通知的线程自己处理\n
    \n

\n

Thread t1 = new Thread( new Runnable(){\n    public void run(){\n        // 若未发生中断,就正常执行任务\n        while(!Thread.currentThread.isInterrupted()){\n            // 正常任务代码……\n        }\n        // 中断的处理代码……\n        doSomething();\n    }\n} ).start();

\n

\n 再次说明:调用interrupt()\n \n 并不是要真正终止掉当前线程\n
\n ,仅仅是设置了一个中断标志。这个中断标志可以给我们用来判断\n \n
什么时候该干什么活\n
\n !什么时候中断\n \n
由我们自己来决定\n
\n ,这样就可以\n \n 安全地终止线程\n \n
了!\n

\n

\n 我们来看看\n \n
源码\n\n
是怎么讲的吧:\n

\n

\n
澳门新萄京网址 23\n

\n

\n 再来看看刚才说抛出的异常是什么东东吧:\n

\n

\n
澳门新萄京网址 24\n

\n

\n 所以说:
interrupt方法压根是不会对线程的状态造成影响的,它仅仅设置一个标志位罢了\n

\n

\n interrupt线程中断还有另外\n \n
两个方法(检查该线程是否被中断)\n
\n :\n

\n

  • \n 静态方法interrupted()–>\n \n 会清除中断标志位\n \n
  • \n \n
    实例\n\n
    方法isInterrupted()–>\n \n 不会清除中断标志位\n \n

\n

\n
澳门新萄京网址 25\n

\n

\n
澳门新萄京网址 26\n

\n

\n 上面还提到了,如果阻塞线程调用了interrupt()方法,那么会\n \n
抛出异常,设置标志位为false,同时该线程会退出阻塞\n
\n
的。我们来测试一波:\n

\n

public class Main {\n    /**\n     * @param args\n     */\n    public static void main(String[] args) {\n        Main main = new Main();\n\n        // 创建线程并启动\n        Thread t = new Thread(main.runnable);\n        System.out.println(\"This is main \");\n        t.start();\n\n        try {\n\n            // 在 main线程睡个3秒钟\n            Thread.sleep(3000);\n        } catch (InterruptedException e) {\n            System.out.println(\"In main\");\n            e.printStackTrace();\n        }\n\n        // 设置中断\n        t.interrupt();\n    }\n\n    Runnable runnable = () -> {\n        int i = 0;\n        try {\n            while (i < 1000) {\n\n                // 睡个半秒钟我们再执行\n                Thread.sleep(500);\n\n                System.out.println(i++);\n            }\n        } catch (InterruptedException e) {\n\n\n            // 判断该阻塞线程是否还在\n            System.out.println(Thread.currentThread().isAlive());\n\n            // 判断该线程的中断标志位状态\n            System.out.println(Thread.currentThread().isInterrupted());\n\n            System.out.println(\"In Runnable\");\n            e.printStackTrace();\n        }\n    };\n}

\n

\n 结果:\n

\n

\n
澳门新萄京网址 27\n

\n

\n 接下来我们分析它的\n \n 执行流程\n \n 是怎么样的:\n

\n

\n
澳门新萄京网址 28\n

\n

\n
2018年4月18日20:32:15(哇,这个方法真的消耗了我非常长的时间)…..感谢@开始de痕迹的指教~\n

\n

\n 该参考资料:\n

\n

  • \n \n
    https\n\n
    ://www.cnblogs.com/w-wfy/p/6414801.html\n
  • \n \n
    http\n\n
    s://www.cnblogs.com/carmanloneliness/p/3516405.html\n
  • \n
  • \n

\n

\n 二、\n \n 总结\n\n

\n

\n 可以发现我们的图是还没有补全的~后续的文章讲到\n \n
同步\n\n
的时候会继续使用上面的图的。在Thread中\n \n
重要的还是那几个可以切换线程状态的方法\n
\n
,还有理解中断的真正含义。\n

\n

\n 使用线程会导致我们\n \n
数据\n\n
不安全,甚至程序无法运行的情况的,这些问题都会再后面讲解到的~\n

\n

\n
之前在学习操作系统的时候根据《计算机操作系统-汤小丹》这本书也做了一点点笔记,都是比较\n
\n 浅显的知识点\n \n 。或许对大家有帮助\n

\n

  • \n 操作系统第一篇【引论】\n
  • \n 操作系统第二篇【\n \n
    进程\n\n
    \n
    管理\n\n
    】\n
  • \n 操作系统第三篇【线程】\n
  • \n 操作系统第四篇【处理机调度】\n
  • \n 操作系统第五篇【死锁】\n
  • \n 操作系统第六篇【存储器管理】\n
  • \n 操作系统第七篇【设备管理】\n

\n

\n 参考资料:\n

\n

  • \n 《Java核心技术卷一》\n
  • \n 《Java并发编程实战》\n
  • \n 《计算机操作系统-汤小丹》\n

\n

\n
如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以\n
\n 关注\n \n
微信公众号\n\n
:Java3y\n
\n 。为了大家方便,刚新建了一下\n \n
qq群:742919422\n
\n ,大家也可以去交流交流。谢谢支持了!\n \n
希望\n\n
能多介绍给其他有需要的朋友\n

“,”原文地址:Thread源码剖析,
感谢原作者分享。”]