• 线程基础知识复习


    线程基础知识复习

    并发相关Java包

    • 涉及到的内容
      • java.util.concurrent
      • java.util.concurrent.atomic
      • java.util.concurrent.locks

    image-20221119180159948

    并发始祖

    • 并发始祖Doug Lea

    image-20221119180339148

    start线程解读

    • 初始程序
    public static void main(String[] args) {
            Thread t1 = new Thread(() ->{
            },"t1");
            t1.start();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    //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是一个native方法
                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
    • 32
    • 33
    • 34
    private native void start0();
    
    • 1
    • native调用了本地方法,我们可以通过下载官网OpenJDK查看其源码

      • thread.c

        java线程是通过start的方法启动执行的,主要内容在native方法start0中

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

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

      image-20221119180932794

      • thread.cpp
        • 终于在这里调用了操作系统的线程启动os::start_thread(thread);

    image-20221119181140731

    Java多线程相关概念

    1把锁

    2个并(并发和并行)

    ①并发

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

    ②并行

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

    并发VS并行

    image-20221119181313683

    3个程(进程 线程 管程)

    • 通过上面start线程的案例,其实进程线程都来源于操作系统。
    ①进程

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

    ②线程

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

    ③管程

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

    Monitor其实是一种同步机制,他的义务是保证(同一时间)只有一个线程可以访问被保护的数据和代码。

    JVM中同步是基于进入和退出监视器对象(Monitor,管程对象)来实现的,每个对象实例都会有一个Monitor对象,

    Monitor对象会和Java对象一同创建并销毁,它底层是由C++语言来实现的。

    进程VS线程

    进程是指运行中的程序,一个进程可以拥有多个线程,线程是进程的一个实体,进程和线程的最大不同在于进程基本上是独立的,而线程不一定,线程共享方法区和堆,线程私有栈、本地方法栈和程序计数器。

    用户线程和守护线程

    Java线程分为用户线程和守护线程

    • 线程的daemon属性为
      • true表示是守护线程
      • false表示是用户线程。

    用户线程

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

    守护线程

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

    总结

    public class DaemonDemo {
        public static void main(String[] args) {
            Thread t1 = new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t 开始运行, " +
                        (Thread.currentThread().isDaemon() ? "守护线程" : "用户线程"));
                while (true) {
    
                }
            }, "t1");
            //t1.setDaemon(true);
            t1.start();
    
            //暂停几秒钟线程
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(Thread.currentThread().getName() + "\t ----end 主线程");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 两种情况
    1. 未加t1.setDaemon(true);,默认是用户线程,他会继续运行,所以灯亮着;可以看到main方法也是用户线程

      image-20221119193236850

    2. 加了t1.setDaemon(true);将t1设置为守护线程,当用户线程main方法结束后自动退出了

    image-20221119193715613

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

    • setDaemon(true)方法必须在start()之前设置,否则报IIIegalThreadStateException异常

  • 相关阅读:
    DDPG算法
    狂砸40亿美元,亚马逊向OpenAI竞争对手Anthropic投资
    [SpringBoot] Enum枚举的使用
    连接表(二)
    git常用指令
    CF1644C Increase Subarray Sums
    MySQL中dd::columns表结构转table过程以及应用
    预训练word2vec--Word2Vec实现(二)
    [微服务源码等]精品基于SpringCloud实现的高并发商城系统-微服务-分布式[包运行成功]
    Flink的API分层、架构与组件原理、并行度、任务执行计划
  • 原文地址:https://blog.csdn.net/qq_44981526/article/details/127940938