拿下这些八股,能在寒冬找到工作吗

拿下这些八股,能在寒冬找到工作吗???


文章目录

1.解决线程安全的问题

1.加锁 synchronized
2.使用cas 轻量级锁
3.Lock
推荐cas

2.JVM有哪些内存区域

程序计数器:主要记录各个线程执行的字节码的地址
虚拟机栈:在jvm运行中存储当前线程运行方法所需的数据,指令、返回地址。
本地方法栈
方法区 存放类的信息
堆:申请的对象

3.对空间大小怎么配置?各区域怎么划?

新生代
老年代
持久代(元空间)
活跃数据的大小:300M
总堆:300M*4 = 1.2 3~4倍活跃数据大小
新生代:450 1~1.5倍活跃数据大小
老年代:750 2~3倍 活跃数据大小
永久代、元空间 300M 1.2~1.5倍fullGC后的永久代空间占用

4.JVM内存区域会发出溢出(OOM)

栈溢出:栈的内存大小是固定的,默认是1M,启动一个线程1,只分配1M的虚拟机栈,把这个方法的局部变量,返回值。每一个方法对应一个栈帧。方法深度太高,把栈的内存用完了。stackOverFlowError
堆溢出:xms xmn 对空间不够用了
方法区溢出:-XXMaxMetaspaceSize=10M 静态变量,常量。加载的静态类太多
本机直接内存溢出:-XX MaxDirectMemorySize=100m 堆外溢出 手动分配和释放,ByteBuffer.allocationDirect()
ooM 后会指出是哪里出现了oom
程序计数器是唯一不会方法oom的区域

5.JVM在创建对象时采用了哪些并发安全机制?

主要指多线程分配内存时。
CAS+失败重试(CAS有一定消耗没有使用)
本地线程分配缓冲(TLAB):每个线程在java堆中预先分配一小块私有内存,也就是本地橙分配缓冲,这样每个线程都单独拥有一个Buffer,如果需要分配内在自己的Buffer分配,这样就不存在竞争的情况,可大大提升分配效率。

6什么是对象头

对象包含:
对象头:
mark word 存储对象运行时的数据:hashocode 锁标识,GC分代年龄
类型指针:指向方法区中创建类的地址
如果是数组,那么还有数组的长度
实例数据:
对齐填充:对象必须是8字节的整数

7 为什么不使用finalize方法

一个对象要被回收,需要经过两次标记。GCROOt引用链,它将被标记一次,随后进行一次筛选,如果覆盖了finalize方法,可以在方法中拯救对象
1.finalize方法的异常不会被处理
2.finalize方法是守护线程,当非守护线程运行结束,他也会结束,不保证能够运行。
3.优先级是10 并不低,只能被使用一次,使用之后,对象会存fq队列中出队。再次回收就会被回收了。

8 什么是栈上分配?

对象的分配过程:
如果开启栈上分配,JVM会先进行栈上分配;
如果没有开启栈上分配或不符合条件,则会进行TLAB分配;
如果TLAB分配不成功且不满足进入老年代的条件,在eden区分配;
如果对象满足了直接进入老年代的条件,那就直接在老年代分配。

目前Hotspot并没有实现真正意义上的栈上分配,实际上是标量替换。
对象的作用域局限在方法fn中,可以使用标量替换的优化手段在栈上分配对象的成员变量,这样就不会生成User对象,大大减轻GC的压力。

并不是所有对象都分配在堆上,除了堆,还可以在栈和tlab本地线程分配缓冲存储对象。
标量是指不可分割的量,如java中基本数据类型和reference类型,相对的一个数据可以继续分解,称为聚合量;

栈上分配是JVM提供的一项优化技术:对于那些线程私有的对象,可以将他们打散分配在栈上,而不是分配在堆上。好处就是可以在函数调用结束后自动消耗,不需要垃圾回收期的介入。对于大量的零散小对象,栈上分配提供了一种很好的对象分配优化策略,站上分配速度快,并且可以有效避免GC带来的负面影响,由于和堆空间相比,栈空间较小,因此对于大对象无法也不适合在栈上分配。
栈上分配的技术基础,两者必须都开启:
关闭TLAB 😦-XX:useTLAB :true(默认打开))
逃逸分析(XXDoEscapeAnalysiiis:true 默认开启):逃逸分析的目的是判断对象的作用于是否有可能逃出函数体。
标量替换(-XX:+EliminateAllocations:true默认开启):允许讲对象打散分配在栈上。比如:若一个对象拥有两个字段,会将这两个字段视作局部变量分配。
只有在server模式下才能弃用要以分析
关闭栈上分配(即:关闭逃逸分析或标量替换中的任何一个)
锁消除:
线程同步本身比较耗性能,如果确定一个对象不会逃逸出线程,无法被其它线程访问到,那该对象的读写就不会存在竞争,则可以消除对该对象的同步锁,通过-XX:+EliminateLocks可以开启同步消除(同步消除不等于移除同步锁,可以是转为偏向锁?)

9怎判断对象的存活

1.引用计数
用一次加1,不用了减1
如果对象之间相互引用 则回收不了
2.可达性分析
从GCroot静态变量 线程栈变量 常量 jni指针

10扩容新生代可以提高GC的效率

因为GC耗时,包括扫描 和 复制两部分
新生代变大的话,扫描和复制的速度都是原来的两倍
但是当扫描时间变长时,可能存活的对象已经死忙了。
新生代垃圾回收的效率,取决于对象的存活时间,所以间隔时间大,可以有更多的对象被回收。避免大量的复制。

11CMS( 关注响应时间)垃圾回收器,以及他的问题

首先他是老年代的垃圾回收器,并发的,减少stw(stop the word)的时间
步骤
初始标记:找到GCRoots直连的对象 stw
并发标记:沿着GCRoots进行标记
重新标记:把并发标记过程中的垃圾进行标记 stw
并发清除: 多个线程一起进行垃圾回收
问题:
cpu敏感:并发是由cpu核心数决定的,所以如果核心数不足4个,垃圾回收会有受限,线程获取不到时间片
浮动垃圾:在并发清理过程中,产生的垃圾,只能在下一次垃圾回收时才能完成标记
内存碎片:因为使用标记清除,所以会有内存碎片。分配不了,就会变成serialOld的垃圾回收器(标记整理)。
可以重启一次项目,

12守护线程和用户线程的区别?

守护线程:Thread.setDaemon(true)
必须在start()方法之前设置为守护线程,否则会报错。
守护线程是为其他线程提供服务,如果用户线程已经结束,守护线程就会结束。

13什么是多线程中的上下文切换

cpu时间片:cpu时间片是cpu分配给每个线程执行的时间段,一般为几十毫秒
上下文切换:当以线程的时间片用完了,或者因为自身原因被迫暂停运行了,这个时候,另外一个线程就会被操作系统选中,来占用处理器。这种一个线程被暂停剥夺使用权,另外一个线程被选中开始或者继续运行的过程就叫做上下切换。
上下文:在这种切出切入的过程中,操作系统需要保存和恢复相应的进度信息,这个进度信息就是“上下文”。

14什么是死锁,死锁的危害?

死锁:是指两个或两个以上的(进程)线程在执行过程中,因争夺资源而造成一种相互等待的现象。如果没有外力作用,将无法推进。
危害:
1.进程得不到正确的结果
2.资源利用率降低
3.会导致产生新的死锁

15 在java中Executor和Executors的区别?

Executor是一个接口
Executors 工具类 提供了一些常用的线程池,Executors.newFixedThreadPool();

16什么是CAS,以及他的缺点

旧值和内存里的值进行比较,相同则进行交换。失败重试
比较,交换
问题:
开销大
只能实现一个共享变量的问题
ABA问题

17Lock接口是什么?对比Synchronized它有什么优势?

Lock接口比同步方法和同步块提供了具有扩展性的锁操作。
condition 可以加条件
tryLock()尝试获取锁
可以实现公平锁

18阻塞队列是什么

BlockQueue
支持阻塞插入 offer()
支持阻塞弹出 take()
队列为空,弹出会阻塞,插入的时候队列满了则阻塞
主要是利用了Condition和lock的等待通知模式实现的。

19什么是Callable和Future

Callabler有返回值,可以抛出返回结果的异常
返回值可以被Future拿到。 Future是拿到一步任务执行的返回值。
Futrue接口表示异步任务,是还没有完成的任务给出的结果,所以Callable用于产生结果,Futrue用于获取结果。

20什么是FutureTask

futureTask是一个可以取消的异步运算,只要当运算完成的时候结果才可以取回,如果运算尚未完成get方法将会阻塞,
一个FutureTask对象可以调用了Callable和Runnalbe的对象进行包装,由于FutureTask也是调用了Runnbale接口,所以他也可以提交给Executor(线程池)执行

21 什么是并发容器的实现

可以理解为通过synchronized来实现同步的容器,串行执行。还有currentHashMap等
要求强一致性,用synchronized来实现
如果是弱一致性,可以用currentHashMap CopyOrWriteList

22 什么是不可变的对象,他对并发应用有什么帮助?

不可变对象就是,对象一旦被创建,他的状态(对象的数据)就不能改变
比如String 基本的包装类,BigInteger
不可变对象是天生线程安全的,他们的常量域是在构造函数中创建的。

23Java内存模型?

计算机多级缓存架构
cpu内部有cpu寄存器
cpu的处理速度远远大于主内存,所以有一个cpu缓存。
在Java内存模型,
每个线程都有自己的工作内存,共享变量是放在主内存中,处理贡献变量需要复制到工作内存。
所以有可见性问题,volital
安全性问题,加锁,CAS
以及重排序问题:cpu的乱序执行

24 什么是线程安全问题?

当多个线程访问某个类或者变量时,不管运行时采用何种调度或者将这些线程如何交替执行,并且在调用代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么他就是线程安全的
(1) 不可变的对象,被final修饰的
(2)加锁或者CAS,使用原子变量(使用的CAS机制)

25一个线程如果出现了运行时异常

(1)异常如果
有被捕获,就会停止执行
(2)如果这个异常被捕获或者抛出,可以继续执行
如果持有对象的监视器对象就会马上释放

26两个线程之间共享数据

1.使用static ,使用共享变量
2.共享遍历的修改会出现线程安全的问题

27Java中的volatile变量有什么作用?

1.确保多线程可见性
线程的工作内存修改了共享变量,出发总线嗅探机制,修改主内存。
2.禁止指令重排序

28生成者消费者的作用是什么?

(1)通过平衡生产者的生成能力和消费者的消费能力来提升整个系统的运行效率
(2)解耦,生成和消费是不同的线程处理

29为什么要用线程池

1.节约资源,避免频繁地创建和销毁线程,达到线程对象的重用。
2.灵活,可以控制并发的数据

30唤醒阻塞的线程

wait 与notify
LockSupport提供的两个方法
park
unpark

31中使用到的线程调度算法是什么?

抢占式
一个线程用完cpu之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。

32什么是线程组,为什么在java中不推荐使用

线程组是ThreadGroup,是为了方便线程的管理
线程池是为/了管理线程的生命周期,复用线程,减少创建销毁线程的开销。
线程租的ThreadGroup最想中的stop,resume,suspend会导致线程安全问题,主要是死锁问题,已经被官方废弃。
线程组不是线程安全的,在使用过程中不能即使获取安全的信息。

33 coypOnWriteArrayList可以适用于什么场景

写实复制的容器,它实现了读操作无锁,写是通过操作底层数组的副本来实现,是一种读写分离的并发策略。
比如说,一些黑明单的添加。数据量不大,且黑名单的加入也不是需要实时写。并发读的操作读。读频繁,写不频繁的场景。

34Thread.sleep(0)的作用

java线程的运行是抢占式。因此可能出现某条线程的一直获取不到cpu控制权。所以使用这个Thread.sleep(0)可以让出cpu的使用权,避免其他线程出现假死现象。

35什么是线程调度器和cpu时间片

线程调度器是一个操作系统服务,他负责为线程分配cpu时间。一旦我们创建一个线程并启动它,他的执行便依赖于线程调度器的实现。
时间片:是cpu分配给每个线程执行的时间段,一般为十几毫秒。
时间片是指将可用的cpu时间分配给可用的Runnable线程的过程,分配cpu时间可以基于线程优先级或者线程等待的时间。

36如何确保main()方法所在的线程是Java程序最后结束的线程

我们可以使用Thread的join方法来确保所有程序创建的线程在main()方法退出前结束。

37什么是JavaTime类,如何创建一个有特定时间间隔的任务

java.util.Timer是一个工具类,可以用于安排一个线程在未来的某个特定时间执行。Time类可以用安排一次性任务或者周期任务。
java.util.TimeTask是一个实现了Runnable接口的抽象类,我们需要去继承这个类来创建我们自己的定时任务并使用Time去安排他的执行。

Time time = new Time();
time.schedule(new MaTask(),TimeUtild.df.get().parse(“”));//设置具体执行时间

38 Java中的Semaphore是什么?

Semaphore就是一个信号量,他的作用实现制某段代码块的并发数。构造函数中传入一个Int整数n,表示某段代码最多只有n个线程可以访问,如果超出了n,那么就要等待。

39为什么代码会重排序?

在执行程序时,为了提升性能,处理器和编译器尝尝会对指令进行冲泡徐,但是不能随意重排序,他需要满足两个条件:在单线程环境下不能改变程序的运行的结果,存在数据依赖关系的不允许重排序。
虽然重排序徐不会影响单线程能的执行结果,但是会破坏多线程的执行语义。

40有三个线程,如何保证他们按照顺序执行

可以先启动T3,T3调用T2,T2调用T1
可以用线程类的join()方法在一个线程中启动另一个线程,等待另外一个线程的完成

41JAVA中的ReadWriteLock是什么?

ReadWriteLock接口的实现ReentrantReadWriteLock
ReentrantLock等大部分锁都是排他锁,这些锁在同一时刻只允许一个线程进行访问,而读写锁在同一时刻可以允许被多个线程访问。读写锁维护了一对锁,读锁和写锁,读写分离,提高并发性。
readLock()
writeLock()

42volatile变量和atomic变量有什么不同

volatile变量可以确保先行关系,即写操作会先行发生于读操作,但是不保证原子性。
AutomicInteger类提供的atomic方法可以保证操作具有原子性,比如说getAndIncrement()方法会原子性的进行增量操作把当前值加1,其他数据类型和引用变量也可以进行相似操作。

43(DCL)单例模式

优雅的方式,单例的变量要加volatile

44 CyclicBarrier和CountDownLatch的区别?

CountDownLatch是一个同步工具类,用来协调多个线程之间的同步,通常用来控制线程等待,他可以让某一个线程等待倒计时结束后,在开始执行。
CyclicBarrier他非常类似,CyclicBarrier可以申请重复使用

45 Java中如何获取到线程Dump文件

使用Java自带的工具VisualVM工具实现(在jdk的bin目录下,双击打开)
jmap -dump:format=b,file=/ / 1654 (安装jdk工具)

46怎么检测一个线程是否持有某个对象监视器?

使用Thread.holdLock(Object o) 当次线程拥有这个对象监视锁会返回true

47Linux 环境下如何查找哪个线程使用cpu最长?

top 显示所有cpu的占用情况,会超过100%,因为是双核。可以找到对应的进程
使用top -p 直接监控指定的进程 ,点击大写的H就显示所有的线程,PID就是线程号
top -H -p pid

48什么是AQS?

AbstractQueueSynchronizer:用来构建锁或者其他同步组件的基础框架,比如ReentrantLocak、ReentrantReadWriteLock和CountDownLatch就是基于AQS实现的。他使用一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作,他是CLH队列锁的一种变体实现。他可以表示实现2中同步方式,独占式和共享式
AQS的主要使用方式是继承,子类通过继承AQS并实现他的抽象方法来管理同步状态,同步器的设计基于模板方法模式,所以如果要实现我们自己的同步工具类就需要覆盖其中几个可重写的方法,比如tryAcquire、tryReleaseShared等。

49线程类的构造方法,静态块是被哪个线程调用的?

线程类的构造方法和静态块是被new这个线程类所在的线程调用的,run是创建的线程调用的

50同步方法和同步块哪个是更好的选择?

同步方法锁的是整个方法,根据业务场景进行选择

51多线程同步和互斥有几种实现方法

1.临界区:适合一个进程内的多线程访问公共区域或代码段时使用
2.互斥量(Mutext):适合不同进程内多线程访问公共区域或代码段时使用,与临界区相似
3.事件:通过线程间出发时间实现同步互斥
4.信号量:与临界区和互斥量不同,可以实现多个线程同时访问公共区域数据,原理与操作系统中PV操作类似,先设置一个访问公共区域的线程最大连接数,每有一个线程访问共享区资源数就减1,直到资源数小于等于0

52什么是竞争条件?你怎样发现和解决竞争

多线程中线程不确定的执行时序导致不正确的结果,就是竞争。
可以采用加锁的方式使线程串行访问临界区

53Java如何实现多线程之间的通讯和写作?

线程与线程之间不是相互独立的个体,他们彼此之间需要通信和协作,最典型的例子就是生产者-消费者问题。
实现该机制的两种方式:
synchronized+wait+notify模式
Lock+Condition模式

54为什么wait和notify方法要在同步块中调用?

主要是因为API强制要求这么做,如果不这么做,代码会抛出IllegalMonitorStateException异常。
如果不加锁的话,wait被调用的时候可能wait的条件已经不满足了。

55JVM中那个参数是用来控制线程的堆栈大小的

-Xms:堆的最小内存
-Xmn:堆的最大内存
-Xss:每一个栈的大小是固定值 默认是1M 被占满会OOM

56什么是阻塞方法

阻塞方法是指调用结果返回之前,当前线程会被挂起,知道得到结果之后才会返回。比如ServerSockert的accpet()方法就是阻塞方法。

57线程优先级的理解

每一个线程都是有优先级的,一般来说优先级高的会先执行,1~10 数字越大越高优先级越高。

58对象的创建过程

1.当Java中遇到一个new关键字
1)检查加载:首先会检查加载,检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查类是否已经被加载,解析和初始化过。
2)分配内存:虚拟机回味新生对象分配内存,为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。
3)内存空间初始化:内存分配我完成后,需要将分配到内存空间都初始化为默认值
4)设置:设置这个对象属于哪个类的实例,如何找到类的元数据信息,对象的哈希码,对象的GC分代年龄信息。这些信息存放在对象的对象头中。
5)对象初始化:此时执行构造方法,进行初始化。此时这个对象才能真正的使用。

59SafePonit是什么?安全区域是什么?

JVM在进行垃圾回收时,会暂停用户线程。在暂停时,会在安全点去执行,安全点是一些指令,作为安全点,比如方法调用,循环跳转、异常跳转等。
GC时要暂停业务线程,并不是抢占式终端(立马把业务线程中断)而是主动式中断。
主动中断是设置一个标志,这个标志是中断标志,各业务运行过程中会不停的主动去轮训这个标志,一旦发现中断标志位true,就会在自己最近的安全点上主动挂起。
安全区域:
为什么需要安全区域?
要是业务线程都不执行,那么程序就没办法进入安全点,对于这种情况,就必须引入安全区域。
安全区域是指能够确保在某一段代码片段中,引用关系不会发生变化,因此,在这个区域中任意地方开始垃圾收集都是安全的。
当用户线程执行到安全区域里面的代码时,首先会标识自己已经进入安全区域,这段时间里JVM要发起GC就不必去管这个线程了。
当线程要离开安全区域时,他要判断JVM是否已经完成了(根节点枚举,或者其他GC中需要暂停用户线程的阶段)
1.如果完成了,那么线程就继续执行
2.否则就一直等待,直到收到可以离开安全区域的信息为止。

60什么是类加载器,类加载器有哪些

类从被加载到虚拟内存中来时,到卸载出内存为止,他的完成生命周期包括:加载、验证、准备、解析、初始化。这就是由类加载器负责的
Bootstrap ClassLoader:最顶层的 C++写的,随着JVM启动,加载核心类库 lib/*.jar
Extention ClassLoader:主要加载lib/ext目录下的jar包,继承URLClassLoader
Application ClassLoader:这是加载classpath下的所有jar包和.class文件。我们自己写的业务代码
Custom ClassLoader:自定义加载器,支持一些个性化的扩展功能。(加密等)

77如何打印JVM日志

一般只要开启gc日志打印,都会默认开启简单日志模式,生成环境建议开启详细GC日志模式
-XX:+printGC
-XX:+printGCDetails

78请介绍常见的JVM参数

1.标准:-开头,所有的hotSpot支持
2.标准:-X开头,特定版本HotSpot支持特定命令
3.高级选项:-XX开头 是开发人员选项,用于调整java HotSpot虚拟机操作的特定区域,这些区域通常有特定的系统要求,并且可能需要对系统配置参数的特权访问,也不能保证所有JVM实现都支持他们,并且可能会发生变化。
在windows上可以通过 java -XX:+printFlagsFinal -version查询所有-XX的
数值类型
bool 类型

79G1垃圾回收器的特点

1.并发与并行
2.分代收集
3.空间整合,基于标记-整理算法,解决内存碎片
4.可以建立可预测的停顿模型
5.将整个Java堆内存模型划分为多个大小相等的region,使得年轻代和老年代不再物理隔离开来。
整个过程分为:
第一个阶段:eden区域不足,新生代内存回收,使用标记复制,把幸存对象复制到s区,stw.如果s区有幸存对象,也会被一起复制到新的幸存区,如果对象参与了15次回收,就会放入老年代
第二个阶段:当老年的占比超过45%以上,会触发并发标记。找到存活对象
重新标记:stw
第三个阶段:并发标记之后,会根据暂停时间目标,选择回收价值高的老年代,以及新生代的区域进行回收。复制时会stw

80 JVM调优工具

优化和问题排查

jps:列出机器上正在运行的虚拟机进程

jstat: 用于监视虚拟机各种运行状态信息的命令工具。可以显示本地或远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。定位虚拟机性能问题的首选工具。

jinfo:查看和修改虚拟机的参数

  • jinfo -sysprops 可以查看由System.getProperties()取得的参数
  • jinfo -flag 未被显示指定的参数的系统默认值
  • jinfo - flags 显示虚拟机的参数

jmap:用于生成对转出快照,还可以查询finalize执行队列,Java堆和永久代的详细信息,如空间使用率,使用的什么垃圾回收期等。

jstack :用于生程虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,可以用来分析定位线程出现长时间停顿的原因。比如死锁、死循环、请求外部资源导致的长时间等待等等。

可视化工具
jconsole
visualvm
arthas 可以用来

81 Java多线程安全,主要是因为Java内存模型

Java内存模型:共享遍历存储在主内存中,线程修改时需要复制到工作内存中,修改完需要回写到主内存中。
只能修饰一个变量
volitail
CAS与院子操作类:AtomicLong accessCount = new AtomicLong(0);
ABA问题针对的是对象,比如String类型,比如String是final类型,这样值一样但是已经是新对象了。

解决方案:加版本号
AtomicSDtampedReference 期望值,修改值,期望版本,版本号加1

LongAdder:减少乐观锁的重试次数
分段的思想:
CPU自选瓶颈问题

HashMap1.8 CAS+Synchronized

82实战应用

读多写少:CopyOrWriteArrayList 读写分离

83 ZGC

jdk11 支持4TB级别的堆(Java13已经16TB)
分区模型和G1一样
三种页面:都是多个三种页面组成了堆
小页面(2M):对象大小<256kb分配
中页面(32M):对象大小 256kb~4M
大页面(>32M):对象大小大于4M
传统垃圾回收器在对象投中记录GC状态
着色指针:(指针就是引用)
32位的 指针寻址范围 是 4G 2的32此方法
ZGC只支持64位的指针,寻址范围是2的64次方。所以地址位只用低42位(4TB),前12位用来着色。
蓝色(初始化,没有标识)44
绿色(标识过:0阶段)42
红色(标识过:1阶段)43
通过修改对象引用的地址高位,来标识对象垃圾回收的状态。
使用的是复制算法
整个阶段划分为7个阶段
初始标记:stw(时间很短,不随着堆空间增大而变长。之和GCRootsd多少有关系) 根据根可达分析,标记直接关联的对象
并发标记:把所有对象全部标识完 三色标记(不暂停用户线程的一个方法 白 灰 黑)
再标记:stw 把并发标记阶段的垃圾再标记一次(把漏标的对象进行标记,读屏障解决漏标问题。遇到读引用的代码,先记录他的引用关系,由这个阶段进行再标记)
并发转移准备:进行分区筛选(有垃圾需要回收的),进行选择性分区回收。不暂停
初始转移:直接关联对象,进行复制到另外一个页面,变化指针的颜色和地址。stw 时间很短
并发转移:被转移的页面中有个转发表,记录引用的旧地址和新地址。如果用户线程要访问这些转移对象,会使用读屏障来解决,访问一个引用时,会从转发表中删除这个引用记录,然后进行把指针修改为新地址。绿色指针还没有处理完,所以绿色指针的修正由下一次垃圾回收的时候进行修正,改为红色。
对象重定位(下次GC)

84什么是进程?

进程可以理解为一个正在执行的程序。
线程是进程的一个执行单元。
更好地利用cpu,比如8核16线程,可以同时完成16个任务,开16个应用 不卡
进程是操作系统分配资源的最小单位
线程是操作系统调度的最小单位
只分配资源,没有调度是没有意义的。

85Java中创建线程

有三种创建线程的方式:继承 Thread类 重写run方法 实现Runnable接口重写run方法 或者实现Callable类重写call方法、
启动的时候需要创建一个Thread类,把对象传递进去,.start启动。
线程池创建线程
pool.execute(new Runnable()){});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值