Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Coudy Hou
JavaGuide
提交
dc904870
J
JavaGuide
项目概览
Coudy Hou
/
JavaGuide
与 Fork 源项目一致
从无法访问的项目Fork
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
JavaGuide
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
dc904870
编写于
12月 16, 2020
作者:
G
guide
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
勘误
上级
ccf21308
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
35 addition
and
31 deletion
+35
-31
docs/java/jvm/Java内存区域.md
docs/java/jvm/Java内存区域.md
+4
-2
docs/java/multi-thread/2020最新Java并发基础常见面试题总结.md
docs/java/multi-thread/2020最新Java并发基础常见面试题总结.md
+5
-5
docs/java/multi-thread/2020最新Java并发进阶常见面试题总结.md
docs/java/multi-thread/2020最新Java并发进阶常见面试题总结.md
+23
-23
docs/operating-system/basis.md
docs/operating-system/basis.md
+3
-1
未找到文件。
docs/java/jvm/Java内存区域.md
浏览文件 @
dc904870
...
@@ -123,7 +123,7 @@ Java 方法有两种返回方式:
...
@@ -123,7 +123,7 @@ Java 方法有两种返回方式:
本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。
本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。
方法执行完毕后相应的栈帧也会出栈并释放内存空间,也会出现
StackOverFlowError 和 OutOfMemoryError
两种错误。
方法执行完毕后相应的栈帧也会出栈并释放内存空间,也会出现
`StackOverFlowError`
和
`OutOfMemoryError`
两种错误。
### 2.4 堆
### 2.4 堆
...
@@ -304,7 +304,9 @@ JDK1.4 中新加入的 **NIO(New Input/Output) 类**,引入了一种基于**
...
@@ -304,7 +304,9 @@ JDK1.4 中新加入的 **NIO(New Input/Output) 类**,引入了一种基于**
### 3.3 对象的访问定位
### 3.3 对象的访问定位
建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有
**①使用句柄**
和
**②直接指针**
两种:
建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有
**①使用句柄**
和
**②直接指针**
两种:
1.
**句柄:**
如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息; !
[
对象的访问定位-使用句柄
](
./pictures/java内存区域/对象的访问定位-使用句柄.png
)
1.
**句柄:**
如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息;
!
[
对象的访问定位-使用句柄
](
./pictures/java内存区域/对象的访问定位-使用句柄.png
)
2.
**直接指针:**
如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而 reference 中存储的直接就是对象的地址。
2.
**直接指针:**
如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而 reference 中存储的直接就是对象的地址。
...
...
docs/java/multi-thread/2020最新Java并发基础常见面试题总结.md
浏览文件 @
dc904870
...
@@ -279,18 +279,18 @@ Process finished with exit code 0
...
@@ -279,18 +279,18 @@ Process finished with exit code 0
## 9. 说说 sleep() 方法和 wait() 方法区别和共同点?
## 9. 说说 sleep() 方法和 wait() 方法区别和共同点?
-
两者最主要的区别在于:
**
sleep 方法没有释放锁,而 wait
方法释放了锁**
。
-
两者最主要的区别在于:
**
`sleep()` 方法没有释放锁,而 `wait()`
方法释放了锁**
。
-
两者都可以暂停线程的执行。
-
两者都可以暂停线程的执行。
-
Wait 通常被用于线程间交互/通信,sleep
通常被用于暂停执行。
-
`wait()`
通常被用于线程间交互/通信,
`sleep() `
通常被用于暂停执行。
-
wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。或者可以使用 wait(long timeout)
超时后线程会自动苏醒。
-
`wait()`
方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的
`notify() `
或者
`notifyAll()`
方法。
`sleep() `
方法执行完成后,线程会自动苏醒。或者可以使用
`wait(long timeout)`
超时后线程会自动苏醒。
## 10. 为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
## 10. 为什么我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?
这是另一个非常经典的 java 多线程面试问题,而且在面试中会经常被问到。很简单,但是很多人都会答不上来!
这是另一个非常经典的 java 多线程面试问题,而且在面试中会经常被问到。很简单,但是很多人都会答不上来!
new 一个 Thread,线程进入了新建状态
;调用 start() 方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。 start() 会执行线程的相应准备工作,然后自动执行 run() 方法的内容,这是真正的多线程工作。 而直接执行 run() 方法,会把 run
方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
new 一个 Thread,线程进入了新建状态
。调用
`start()`
方法,会启动一个线程并使线程进入了就绪状态,当分配到时间片后就可以开始运行了。
`start()`
会执行线程的相应准备工作,然后自动执行
` run() `
方法的内容,这是真正的多线程工作。 但是,直接执行
`run()`
方法,会把
`run()`
方法当成一个 main 线程下的普通方法去执行,并不会在某个线程中执行它,所以这并不是多线程工作。
**总结: 调用
start 方法方可启动线程并使线程进入就绪状态,而 run 方法只是 thread 的一个普通方法调用,还是在主线程里
执行。**
**总结: 调用
`start()` 方法方可启动线程并使线程进入就绪状态,直接执行 `run()` 方法的话不会以多线程的方式
执行。**
## 公众号
## 公众号
...
...
docs/java/multi-thread/2020最新Java并发进阶常见面试题总结.md
浏览文件 @
dc904870
...
@@ -74,9 +74,9 @@
...
@@ -74,9 +74,9 @@
因为监视器锁(monitor)是依赖于底层的操作系统的
`Mutex Lock`
来实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高。
因为监视器锁(monitor)是依赖于底层的操作系统的
`Mutex Lock`
来实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高。
庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对
synchronized 较大优化,所以现在的 synchronized
锁效率也优化得很不错了。JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。
庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对
`synchronized`
较大优化,所以现在的
`synchronized`
锁效率也优化得很不错了。JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。
所以,你会发现目前的话,不论是各种开源框架还是 JDK 源码都大量使用了
synchronized
关键字。
所以,你会发现目前的话,不论是各种开源框架还是 JDK 源码都大量使用了
`synchronized`
关键字。
### 1.2. 说说自己是怎么使用 synchronized 关键字
### 1.2. 说说自己是怎么使用 synchronized 关键字
...
@@ -296,9 +296,9 @@ JDK1.6 对锁的实现引入了大量的优化,如偏向锁、轻量级锁、
...
@@ -296,9 +296,9 @@ JDK1.6 对锁的实现引入了大量的优化,如偏向锁、轻量级锁、
`synchronized`
关键字和
`volatile`
关键字是两个互补的存在,而不是对立的存在!
`synchronized`
关键字和
`volatile`
关键字是两个互补的存在,而不是对立的存在!
-
**
volatile 关键字**
是线程同步的
**轻量级实现**
,所以
**volatile 性能肯定比 synchronized 关键字要好**
。但是
**volatile 关键字只能用于变量而 synchronized
关键字可以修饰方法以及代码块**
。
-
**
`volatile` 关键字**
是线程同步的
**轻量级实现**
,所以
**`volatile `性能肯定比` synchronized `关键字要好**
。但是
**`volatile` 关键字只能用于变量而 `synchronized`
关键字可以修饰方法以及代码块**
。
-
**
volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized
关键字两者都能保证。**
-
**
`volatile` 关键字能保证数据的可见性,但不能保证数据的原子性。`synchronized`
关键字两者都能保证。**
-
**
volatile 关键字主要用于解决变量在多个线程之间的可见性,而 synchronized
关键字解决的是多个线程之间访问资源的同步性。**
-
**
`volatile`关键字主要用于解决变量在多个线程之间的可见性,而 `synchronized`
关键字解决的是多个线程之间访问资源的同步性。**
## 3. ThreadLocal
## 3. ThreadLocal
...
@@ -814,7 +814,7 @@ pool-1-thread-1 End. Time = Tue Nov 12 20:59:54 CST 2019
...
@@ -814,7 +814,7 @@ pool-1-thread-1 End. Time = Tue Nov 12 20:59:54 CST 2019
### 5.1. 介绍一下 Atomic 原子类
### 5.1. 介绍一下 Atomic 原子类
Atomic
翻译成中文是原子的意思。在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的。在我们这里 Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
`Atomic`
翻译成中文是原子的意思。在化学上,我们知道原子是构成一般物质的最小单位,在化学反应中是不可分割的。在我们这里 Atomic 是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
所以,所谓原子类说简单点就是具有原子/原子操作特征的类。
所以,所谓原子类说简单点就是具有原子/原子操作特征的类。
...
@@ -828,29 +828,29 @@ Atomic 翻译成中文是原子的意思。在化学上,我们知道原子是
...
@@ -828,29 +828,29 @@ Atomic 翻译成中文是原子的意思。在化学上,我们知道原子是
使用原子的方式更新基本类型
使用原子的方式更新基本类型
-
AtomicInteger
:整形原子类
-
`AtomicInteger`
:整形原子类
-
AtomicLong
:长整型原子类
-
`AtomicLong`
:长整型原子类
-
AtomicBoolean
:布尔型原子类
-
`AtomicBoolean`
:布尔型原子类
**数组类型**
**数组类型**
使用原子的方式更新数组里的某个元素
使用原子的方式更新数组里的某个元素
-
AtomicIntegerArray
:整形数组原子类
-
`AtomicIntegerArray`
:整形数组原子类
-
AtomicLongArray
:长整形数组原子类
-
`AtomicLongArray`
:长整形数组原子类
-
AtomicReferenceArray
:引用类型数组原子类
-
`AtomicReferenceArray`
:引用类型数组原子类
**引用类型**
**引用类型**
-
AtomicReference
:引用类型原子类
-
`AtomicReference`
:引用类型原子类
-
AtomicStampedReference
:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
-
`AtomicStampedReference`
:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
-
AtomicMarkableReference
:原子更新带有标记位的引用类型
-
`AtomicMarkableReference`
:原子更新带有标记位的引用类型
**对象的属性修改类型**
**对象的属性修改类型**
-
AtomicIntegerFieldUpdater
:原子更新整形字段的更新器
-
`AtomicIntegerFieldUpdater`
:原子更新整形字段的更新器
-
AtomicLongFieldUpdater
:原子更新长整形字段的更新器
-
`AtomicLongFieldUpdater`
:原子更新长整形字段的更新器
-
AtomicReferenceFieldUpdater
:原子更新引用类型字段的更新器
-
`AtomicReferenceFieldUpdater`
:原子更新引用类型字段的更新器
### 5.3. 讲讲 AtomicInteger 的使用
### 5.3. 讲讲 AtomicInteger 的使用
...
@@ -916,11 +916,11 @@ CAS 的原理是拿期望的值和原本的一个值作比较,如果相同则
...
@@ -916,11 +916,11 @@ CAS 的原理是拿期望的值和原本的一个值作比较,如果相同则
### 6.1. AQS 介绍
### 6.1. AQS 介绍
AQS 的全称为(
AbstractQueuedSynchronizer),这个类在 java.util.concurrent.locks
包下面。
AQS 的全称为(
`AbstractQueuedSynchronizer`
),这个类在
` java.util.concurrent.locks `
包下面。
![
AQS类
](
https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/AQS类.png
)
![
AQS类
](
https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/AQS类.png
)
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的
ReentrantLock,Semaphore,其他的诸如 ReentrantReadWriteLock,SynchronousQueue,FutureTask
等等皆是基于 AQS 的。当然,我们自己也能利用 AQS 非常轻松容易地构造出符合我们自己需求的同步器。
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的
`ReentrantLock`
,
`Semaphore`
,其他的诸如
`ReentrantReadWriteLock`
,
`SynchronousQueue`
,
`FutureTask`
等等皆是基于 AQS 的。当然,我们自己也能利用 AQS 非常轻松容易地构造出符合我们自己需求的同步器。
### 6.2. AQS 原理分析
### 6.2. AQS 原理分析
...
@@ -1012,9 +1012,9 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
...
@@ -1012,9 +1012,9 @@ tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true
### 6.3. AQS 组件总结
### 6.3. AQS 组件总结
-
**
Semaphore(信号量)-允许多个线程同时访问:**
synchronized 和 ReentrantLock 都是一次只允许一个线程访问某个资源,Semaphore
(信号量)可以指定多个线程同时访问某个资源。
-
**
`Semaphore`(信号量)-允许多个线程同时访问:**
`synchronized`
和
`ReentrantLock`
都是一次只允许一个线程访问某个资源,
`Semaphore`
(信号量)可以指定多个线程同时访问某个资源。
-
**
CountDownLatch (倒计时器):**
CountDownLatch
是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。
-
**
`CountDownLatch `(倒计时器):**
`CountDownLatch`
是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。
-
**
CyclicBarrier(循环栅栏):**
CyclicBarrier 和 CountDownLatch 非常类似,它也可以实现线程间的技术等待,但是它的功能比 CountDownLatch 更加复杂和强大。主要应用场景和 CountDownLatch 类似。CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier 默认的构造方法是 CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用 await()方法告诉 CyclicBarrier
我已经到达了屏障,然后当前线程被阻塞。
-
**
`CyclicBarrier`(循环栅栏):**
`CyclicBarrier`
和
`CountDownLatch`
非常类似,它也可以实现线程间的技术等待,但是它的功能比
`CountDownLatch`
更加复杂和强大。主要应用场景和
`CountDownLatch`
类似。
`CyclicBarrier`
的字面意思是可循环使用(
`Cyclic`
)的屏障(
`Barrier`
)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。
`CyclicBarrier`
默认的构造方法是
`CyclicBarrier(int parties)`
,其参数表示屏障拦截的线程数量,每个线程调用
`await()`
方法告诉
`CyclicBarrier`
我已经到达了屏障,然后当前线程被阻塞。
### 6.4. 用过 CountDownLatch 么?什么场景下用的?
### 6.4. 用过 CountDownLatch 么?什么场景下用的?
...
...
docs/operating-system/basis.md
浏览文件 @
dc904870
...
@@ -271,7 +271,9 @@
...
@@ -271,7 +271,9 @@
### 4.3 虚拟存储器
### 4.3 虚拟存储器
👨💻
**面试官**
:都说了虚拟内存了。你再讲讲
**虚拟存储器**
把!
> **勘误:虚拟存储器又叫做虚拟内存,都是 Virtual Memory 的翻译,属于同一个概念。**
👨💻
**面试官**
:~~都说了虚拟内存了。你再讲讲
**虚拟存储器**
把!~~
🙋
**我**
:
🙋
**我**
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录