• 第二章:线程基础知识复习


    为什么要学好多线程如此重要?

    硬件方面

    摩尔定律

    它是由英特尔创始人之一-Gordon Moore(戈登●摩尔)提出来的。其内容为: .

    当价格不变时,集成电路上可容纳的元器件的数目约每隔18-24个月便会增加一倍,性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18-24个月翻- -倍以 上。这-一定律揭示了信息技术进步的速度。

    可是从2003年开始CPU主频已经不再翻倍,而是采用多核而不是更快的主频。

    摩尔定律失效了,0(T_ τ)o

    在主频不再提高且核数在不断增加的情况下,要想让程序更快就要用到并行或并发编程

    软件方面

    • 面试B格可以高一点点, ^^
    • 充分利用多核处理器
    • 提高程序性能,高并发系统
    • 提高程序吞吐量,异步+回调等生产需求

    弊端及问题

    • 线程安全问题
      • i++
      • 集合是否安全
    • 线程锁问题
    • 线程性能问题

    从 start 一个线程说起

    初始代码

    public class ThreadTest {
        public static void main(String[] args) {
            new Thread(() -> {
    
            }, "t1").start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Thread类中start() 方法

    public synchronized void start() {
            /**
             * This method is not invoked for the main method thread or "system"
             * group threads created/set up by the VM. Any new functionality added
             * to this method in the future may have to also be added to the VM.
             *
             * A zero status value corresponds to state "NEW".
             */
            if (threadStatus != 0)
                throw new IllegalThreadStateException();
    
            /* Notify the group that this thread is about to be started
             * so that it can be added to the group's list of threads
             * and the group's unstarted count can be decremented. */
            group.add(this);
    
            boolean started = false;
            try {
                start0();
                started = true;
            } finally {
                try {
                    if (!started) {
                        group.threadStartFailed(this);
                    }
                } catch (Throwable ignore) {
                    /* do nothing. If start0 threw a Throwable then
                      it will be passed up the call stack */
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    调用了 本地方法 start0();

    private native void start0();
    
    • 1

    native调用了本地方法,我们可以通过下载官网OpenJDK查看其源码

    openJdk 下载地址:jdk8u/jdk8u/hotspot: log (java.net)

    可能会出现下载错误,以及丢失的问题,所以在云盘分享出来了

    链接:https://pan.baidu.com/s/1IdUWWTAhHBU3w88gGQWMeg
    提取码:fme6

    Openjdk的写JNI一般是一一对应的,Thread.java对应的就是 Thread.c

    image-20221119155931803

    start0其实就是JVM_StartThread。此时查看源代码可以看到在jvm.h中找到了声明,jvm.cpp中有实现。

    image-20221119160330667

    image-20221119160155139

    thread.cpp : 最终在这个类中启动了线程

    image-20221119160404604

    Java多线程相关概念

    并发

    ​ 是在同一实体上的多个事件,是在同一台处理器上“同时”处理多个任务,同一时刻,其实是只有一个事件在发生。

    并行

    ​ 是在不同实体上的多个事件,是在多台处理器上同时处理多个任务,同一时刻,大家都真的在做事情,你做你的,我做我的

    并行 vn 并发

    image-20221119161018162

    无论是进程还是线程,都属于操作系统级别的,和语言无关

    线程

    ​ 也被称为轻量级进程,在同一个进程内基本会有一个或多个线程,是大多数操作系统进行调度的基本单元。

    进程

    ​ 系统中运行的一个应用程序就是一个进程,每一个进程都有它自己的内存空间和系统资源。

    管程

    ​ Monitor(监视器),也就是我们平时说的

    • Monitor其实是一种同步机制,他的义务是保证(同一时间)只有一个线程可以访问被保护的数据和代码。
    • JVM中同步是基于进入和退出监视器对象(Monitor,管程对象)来实现的,每个对象实例都会有一个Monitor对象,
    • Monitor对象会和Java对象一同创建并销毁,它底层是由C++语言来实现的。

    ​ 锁 == 管程

    用户线程和守护线程

    用户线程

    是系统的工作线程,它会完成这个程序需要完成的业务操作

    一般在不指明守护线程的情况下,默认都是用户线程

    守护线程

    是一种特殊的线程,为其他线程服务的,在后台默默地完成一些系统性的服务,比如垃圾回收线程。

    守护线程作为-一个服务线程,没有服务对象就没有必要继续运行了,如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了。所以假如当系统只剩下守护线程的时候,java虚拟机会自动退出。

    关于守护线程的俩个方法

    • void setDaemon(boolean on) : true 设置守护线程, false: 非守护线程
    • 设置守护线程必须在线程启动之前设置,否则会报:IllegalThreadStateException 异常
    • boolean isDaemon() : 判断当前线程是否为守护线程

    代码演示

    public class DaemonTest {
        public static void main(String[] args) {
            Thread t1 = new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " 开始工作,"
                        + (Thread.currentThread().isDaemon()? "守护线程":"用户线程"));
            }, "t1");
    
            // 将t1设置守护线程
            t1.setDaemon(true);
            t1.start();
            
            try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}
    
            System.out.println(Thread.currentThread().getName() + " 线程结束");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16


    各位彭于晏,如有收获点个赞不过分吧…✌✌✌

    Alt


    扫码关注公众号 【我不是秃神】 回复 JUC 可下载 MarkDown 笔记

  • 相关阅读:
    如何使用 KubeSeal 高效加密和管理 Kubernetes 集群的 Secret
    第15章 基数法则
    挑战算法题:四数之和
    php生成海报和指定文字
    HTTP原理入门
    vue3组件通信
    Python第三方库之MedPy
    金仓数据库KingbaseES客户端编程接口指南-Nodejs(3. Nodejs驱动使用说明)
    Ubuntu系统中tree的用法
    网络安全(黑客技术)自学笔记
  • 原文地址:https://blog.csdn.net/aetawt/article/details/128044834