Java高并发编程详解学习笔记(一)

前言:要秋招了,复习一下应对秋招,纠结该先看啥,最后决定先学习《Java高并发编程详解》,此博客为看书所写的笔记,因为是笔记,所以会只记比较重要的东西,不适合初学者

参考:

https://blog.csdn.net/q610376681/article/details/87922812

目录

第一章 快速认识线程

1.1 线程的生命周期

1.2 模板设计模式在Thread中的应用

1.3 策略模式在Thread中的使用

第二章 深入理解Thread构造函数

2.1 线程的命名

2.2 线程的父子关系

2.3 Thread与ThreadGroup

2.4 Thread与JVM虚拟机栈

2.4.1 JVM内存结构

2.4.2 Thread与虚拟机栈的关系

2.5 守护线程


第一章 快速认识线程

当JVM启动时启动了一个进程,如果在进程中增加线程呢?用Thread.start即可,Thread类的对象在没调用start方法时仅仅是一个对象,调用了才能启动一个线程。

JVM启动时创建的不知有main线程,还有一些垃圾回收线程,RMI线程等等。

1.1 线程的生命周期

NEW是Thread对象还没调用start方法时的状态

Runnable是调用Start方法但是还没获取到CPU的调度资格,处于此状态下的线程只能意外终止或者进入Running状态

Running状态是获取到CPU正在运行的线程,可以通过stop直接进入Terminated状态,也可能因为调用sleep,wait,调用了某个阻塞的IO,需要获取某个锁资源而进入Blocked状态,或者是因为cpu轮转或者yield放弃cpu而进入Runnable状态。

Blocked状态是线程进入了阻塞状态,可以直接进入Terminated状态,可以因休眠结束、被唤醒、获取到了锁资源、阻塞过程中被打断而进入Runnable状态。

Terminated是线程的最终形态,该状态下不会切换到任何状态

注:一个Thread只能start一次

1.2 模板设计模式在Thread中的应用

我们都知道最终start会调用run方法来新开线程,这其实是典型的模板模式,父类编写算法结构代码,子类实现逻辑细节。

在这里父类开启线程,子类重写run方法实现具体细节。

模板模式介绍:https://www.jianshu.com/p/800a44c1d9dd

1.3 策略模式在Thread中的使用

当我们模拟一个多线程叫号程序时,当前的号码是共享资源,可以通过将共享变量置为static来解决,但是如果共享资源很多且要经过比较复杂的计算呢?不可能都用static修饰,Java提供了一个接口Runnable专门解决该问题,将线程的控制和业务逻辑的运行分离开来。

TicketWindow extend Threads {
    private static int index = 1;
}

 我们新建类实现接口,将具体的业务逻辑在接口中完成,然后新建thread时将接口实现类传入,它便会调用我们接口实现的方法,完成相应的业务逻辑。

策略模式讲解:https://baijiahao.baidu.com/s?id=1638224488060180625&wfr=spider&for=pc

 

第二章 深入理解Thread构造函数

2.1 线程的命名

线程默认以Thread-作为前缀与一个自增数字进行组合,也可在新建的时候进行命名,线程启动之前可以修改名字,启动后名字不能修改。

2.2 线程的父子关系

任何创建的线程都会有一个父线程,一个线程的创建肯定是由另一个线程完成的,被创建线程的父线程是创建它的线程。

2.3 Thread与ThreadGroup

Thread的构造函数中,可以显式地指定线程的group,如果不指定,则子线程会加入父线程所在的线程组,main线程所在的ThreadGroup称为main

2.4 Thread与JVM虚拟机栈

Thread的构造函数中,有一个特殊的参数stackSize。

一般情况下,创建线程的时候不会手动指定栈内存的地址空间字节数组,统一通过xss参数进行设置即可,stacksize越大表示线程内方法调用递归的深度就越深,stacksize越小则代表创建的线程数据量越多。

2.4.1 JVM内存结构

程序计数器:无论任何语言都需要由操作系统通过控制总线向CPU发送机器指令,程序计数器在JVM中所起的作用就是用于存放当前线程接下来将要执行的字节码指令、分支、循环、跳转、异常处理等信息,任何时候,一个处理器只执行其中一个线程中的指令,为了能够在CPU时间片轮转切换上下文之后顺利回到正确的执行位置,每条线程都需要具有独立的程序计数器。

Java虚拟机栈:这也是线程私有的,用于存放局部变量表、操作栈、动态链接、方法出口等信息,每个栈帧存放对应时刻的以上信息,方法的调用对应着栈帧的出栈和入栈。

本地方法栈:Java中提供了调用本地方法的接口,也就是C/C++程序,一些网络通信,文件操作的底层便需要调用本地方法,JVM为本地方法所划分的内存区域便是本地方法栈。

堆内存:堆内存是JVM中最大的一块内存区域,被所有的线程所共享,Java在运行期间创建的所有对象几乎都存放在该内存区域,因此该区域也是垃圾回收器重点照顾的区域,因此有些时候堆内存被称为“GC堆”,堆内存一般被分为新生代和老年代,更细致的分为Eden区、From Survivor区和To Survivor区。

方法区:方法区也是多个线程所共享的内存区域,它主要用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器(JIT)编译后的代码等数据,虽然在Java虚拟机规范中,将方法区分为堆内存的一个逻辑分区,但是它还是经常被成为非堆,有时也被称为持久代。

Java 8元空间:上面介绍了JVM的内存划分,在JDK1.8之前内存大概都是这样划分的,但是自从JDK1.8起,JVM的内存区域发生了一些改变,实际上是持久代被彻底删除,取而代之的是元空间。

2.4.2 Thread与虚拟机栈的关系

可以粗略的认为 Java进程内存=堆内存+栈内存*线程个数

当虚拟机栈越大,其它不变,可创建的线程数量就越小;当堆内存越大,可创建的线程数量也会越小,但影响不明显

一个粗略估算最大线程数量的方法

线程数量=((最大地址空间)-JVM堆内存-系统保留内存)/ThreadStackSize

2.5 守护线程

当JVM中没有个一个非守护线程,既JVM中全是守护线程时JVM会退出。

如垃圾回收线程是守护线程,当非守护线程main结束后垃圾回收线程会自动结束。

线程可以通过setDaemon设置守护或非守护线程。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值