Skip to content

Commit 24b957b

Browse files
committed
增加Java并发面试题
1 parent da27883 commit 24b957b

File tree

6 files changed

+39
-21
lines changed

6 files changed

+39
-21
lines changed

Java/JVM高频面试题.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ GC(`Garbage Collection`),垃圾回收,是Java与C++的主要区别之一
393393

394394
**老年代空间不足**
395395

396-
老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等。为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组。除此之外,可以通过 `-Xmn` 参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。还可以通过 `-XX:MaxTenuringThreshold` 调大对象进入老年代的年龄,让对象在新生代多存活一段时间。
396+
老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等。为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组、注意编码规范避免内存泄露。除此之外,可以通过 `-Xmn` 参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。还可以通过 `-XX:MaxTenuringThreshold` 调大对象进入老年代的年龄,让对象在新生代多存活一段时间。
397397

398398
**空间分配担保失败**
399399

Java/Java8.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
3434
## 函数式编程
3535

36-
面向对象编程:面向对象的语言,一切皆对象,如果想要调用一个函数,函数必须属于一个类或对象,然后在使用类或对象进行调用。面向对象编程会多写很多可能是重复的代码行
36+
面向对象编程:面向对象的语言,一切皆对象,如果想要调用一个函数,函数必须属于一个类或对象,然后在使用类或对象进行调用。面向对象编程可能需要多写很多重复的代码行
3737

3838
```java
3939
Runnable runnable = new Runnable() {

Java/Java基础面试题.md

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -645,13 +645,11 @@ public class LifeCycle {
645645

646646
## 常见的关键字有哪些?
647647

648-
### static
648+
**static**
649649

650650
static可以用来修饰类的成员方法、类的成员变量。
651651

652-
**静态变量**
653-
654-
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
652+
static变量也称作**静态变量**,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
655653

656654
以下例子,age为非静态变量,则p1打印结果是:`Name:zhangsan, Age:10`;若age使用static修饰,则p1打印结果是:`Name:zhangsan, Age:12`,因为static变量在内存只有一个副本。
657655

@@ -681,9 +679,7 @@ public class Person {
681679
}
682680
```
683681

684-
**静态方法**
685-
686-
static方法一般称作静态方法。静态方法不依赖于任何对象就可以进行访问,通过类名即可调用静态方法。
682+
static方法一般称作**静态方法**。静态方法不依赖于任何对象就可以进行访问,通过类名即可调用静态方法。
687683

688684
```java
689685
public class Utils {
@@ -697,9 +693,7 @@ public class Utils {
697693
}
698694
```
699695

700-
**静态代码块**
701-
702-
静态代码块只会在类加载的时候执行一次。以下例子,startDate和endDate在类加载的时候进行赋值。
696+
**静态代码块**只会在类加载的时候执行一次。以下例子,startDate和endDate在类加载的时候进行赋值。
703697

704698
```java
705699
class Person {
@@ -744,15 +738,15 @@ public class OuterClass {
744738
}
745739
```
746740

747-
### final
741+
**final**
748742

749743
1. **基本数据**类型用final修饰,则不能修改,是常量;**对象引用**用final修饰,则引用只能指向该对象,不能指向别的对象,但是对象本身可以修改。
750744

751745
2. final修饰的方法不能被子类重写
752746

753747
3. final修饰的类不能被继承。
754748

755-
### this
749+
**this**
756750

757751
`this.属性名称`指访问类中的成员变量,可以用来区分成员变量和局部变量。如下代码所示,`this.name`访问类Person当前实例的变量。
758752

@@ -796,7 +790,7 @@ public class Person {
796790
}
797791
```
798792

799-
### super
793+
**super**
800794

801795
super 关键字用于在子类中访问父类的变量和方法。
802796

Java/Java并发面试题.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,9 @@ class RunnableDemo implements Runnable {
397397

398398
### 什么是线程死锁?
399399

400-
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止
400+
线程死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去
401401

402-
如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。
402+
如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方持有的资源,所以这两个线程就会互相等待而进入死锁状态。
403403

404404
![死锁](https://gitee.com/tysondai/img/raw/master/死锁.png)
405405

@@ -1121,3 +1121,28 @@ public final void lazySet(int i, int newValue)//最终 将index=i 位置的元
11211121
- AtomicStampedReference:带有版本号的引用类型原子类。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。
11221122
- AtomicMarkableReference :原子更新带有标记的引用类型。该类将 boolean 标记与引用关联起来
11231123

1124+
## 为什么要使用Executor线程池框架呢?
1125+
1126+
- 每次执行任务都通过new Thread()去创建线程,比较消耗性能,创建一个线程是比较耗时、耗资源的
1127+
- 调用new Thread()创建的线程缺乏管理,可以无限制的创建,线程之间的相互竞争会导致过多占用系统资源而导致系统瘫痪
1128+
- 直接使用new Thread()启动的线程不利于扩展,比如定时执行、定期执行、定时定期执行、线程中断等都不好实现
1129+
1130+
## 如何停止一个正在运行的线程?
1131+
1132+
1. 使用共享变量的方式。共享变量可以被多个执行相同任务的线程用来作为是否停止的信号,通知停止线程的执行。
1133+
2. 使用interrupt方法终止线程。当一个线程被阻塞,处于不可运行状态时,即使主程序中将该线程的共享变量设置为true,但该线程此时根本无法检查循环标志,当然也就无法立即中断。这时候可以使用Thread提供的interrupt()方法,因为该方法虽然不会中断一个正在运行的线程,但是它可以使一个被阻塞的线程抛出一个中断异常,从而使线程提前结束阻塞状态。
1134+
1135+
## 什么是Daemon线程?
1136+
1137+
后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线程,并且这个线程并不属于程序中不可或缺的部分。因此,当所有的非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程。反过来说,只要有任何非后台线程还在运行,程序就不会终止。必须在线程启动之前调用setDaemon()方法,才能把它设置为后台线程。
1138+
1139+
注意:后台进程在不执行finally子句的情况下就会终止其run()方法。
1140+
1141+
比如:JVM的垃圾回收线程就是Daemon线程,Finalizer也是守护线程。
1142+
1143+
## SynchronizedMap和ConcurrentHashMap有什么区别?
1144+
1145+
SynchronizedMap一次锁住整张表来保证线程安全,所以每次只能有一个线程来访问map。
1146+
1147+
JDK1.8 ConcurrentHashMap采用CAS和synchronized来保证并发安全。数据结构采用数组+链表/红黑二叉树。synchronized只锁定当前链表或红黑二叉树的首节点,支持并发访问、修改。
1148+
另外ConcurrentHashMap使用了一种不同的迭代方式。当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。

Java/Java集合面试题.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ return h&(length-1); //第三步 取模运算
180180

181181
1.7链表新节点采用的是头插法,这样在线程一扩容迁移元素时,会将元素顺序改变,导致两个线程中出现元素的相互指向而形成循环链表,1.8采用了尾插法,避免了这种情况的发生。
182182

183-
原数组的元素在重新计算hash之后,因为数组容量n变为2倍,那么n-1的mask范围在高位多1bit。在元素拷贝过程不需要重新计算元素在数组中的位置,只需要看看原来的hash值新增的那个bit是1还是0,是0的话索引没变,是1的话索引变成“原索引+oldCap”(根据`e.hash & (oldCap - 1) == 0`判断) 。这样可以省去重新计算hash值的时间,而且由于新增的1bit是0还是1可以认为是随机的,因此resize的过程会均匀的把之前的冲突的节点分散到新的bucket。
183+
原数组的元素在重新计算hash之后,因为数组容量n变为2倍,那么n-1的mask范围在高位多1bit。在元素拷贝过程不需要重新计算元素在数组中的位置,只需要看看原来的hash值新增的那个bit是1还是0,是0的话索引没变,是1的话索引变成“原索引+oldCap”(根据`e.hash & oldCap == 0`判断) 。这样可以省去重新计算hash值的时间,而且由于新增的1bit是0还是1可以认为是随机的,因此resize的过程会均匀的把之前的冲突的节点分散到新的bucket。
184184

185185
### put方法流程?
186186

@@ -202,7 +202,7 @@ return h&(length-1); //第三步 取模运算
202202

203203
### 在解决 hash 冲突的时候,为什么选择先用链表,再转红黑树?
204204

205-
因为红黑树需要进行左旋,右旋,变色这些操作来保持平衡,而单链表不需要。所以,当元素个数小于8个的时候,采用链表结构可以保证查询性能。而当元素个数大于8个的时候, 红黑树搜索时间复杂度是 `O(logn)`,而链表是 `O(n)`此时使用红黑树可以加快查询速度
205+
因为红黑树需要进行左旋,右旋,变色这些操作来保持平衡,而单链表不需要。所以,当元素个数小于8个的时候,采用链表结构可以保证查询性能。而当元素个数大于8个的时候并且数组容量大于64,会采用红黑树结构。因为红黑树搜索时间复杂度是 `O(logn)`,而链表是 `O(n)`在n比较大的时候,使用红黑树可以加快查询速度
206206

207207
### HashMap 的长度为什么是 2 的幂次方?
208208

网络/计算机网络高频面试题.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
![](https://gitee.com/tysondai/img/raw/master/tcp5layer2.png)
4242

43-
TCP/IP五层模型:应用层、传输层、网络层、数据链路层、物理层。
43+
五层模型:应用层、传输层、网络层、数据链路层、物理层。
4444

4545
- **应用层**:为应用程序提供交互服务。在互联网中的应用层协议很多,如域名系统DNS、HTTP协议、SMTP协议等。
4646
- **传输层**:负责向两台主机进程之间的通信提供数据传输服务。传输层的协议主要有传输控制协议TCP和用户数据协议UDP。
@@ -159,7 +159,6 @@ Content-Length:112
159159
- GET请求参数通过URL传递,POST的参数放在请求体中。
160160
- GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把请求头和请求体一并发送出去;而对于POST,浏览器先发送请求头,服务器响应100 continue,浏览器再发送请求体。
161161
- GET请求会被浏览器主动缓存,而POST不会,除非手动设置。
162-
- GET请求只能进行url编码,而POST支持多种编码方式。
163162
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
164163

165164
## HTTP长连接和短连接?

0 commit comments

Comments
 (0)