一,jvm类加载机制
1.1 什么是类加载机制
java代码编译后就会生成JVM能够识别的二进制字节流文件*.class文件,将class文件加载到内存,最终成为可以被JVM直接使用的Java类型,这个过程叫做JVM的类加载机制。
1.2 类加载过程
class文件中的“类”从加载到JVM内存中,到卸载出内存过程有七个生命周期阶段:

java代码编译后就会生成JVM能够识别的二进制字节流文件*.class文件,将class文件加载到内存,最终成为可以被JVM直接使用的Java类型,这个过程叫做JVM的类加载机制。
class文件中的“类”从加载到JVM内存中,到卸载出内存过程有七个生命周期阶段:

作用:
JVM Process Status Tool,显示虚拟机进程。
用法:
jps [-qmlvV]
调用线程池的shutdown()或shutdownNow()方法,线程当前状态如何处理
| 线程当前状态 | shutdown() | shutdownNow() |
|---|---|---|
| 正在执行任务 | 继续执行,完成后退出 | 中断线程,但任务可能继续执行,取决于是否响应中断,不是"完成后退出",而是任务执行完后检测到 STOP 状态退出,如果任务不响应中断,会一直执行到完成(可能无限循环) |
| 等待获取任务 | 中断空闲线程, 线程在 workQueue.take() 处被中断,抛出InterruptedException异常,线程池自己捕捉到这个异常,继续自旋判断如果队列为空,rerurn null后,线程自然结束。 | 中断所有线程, 线程在 workQueue.take() 处被中断,抛出InterruptedException异常,线程池自己捕捉到这个异常,继续自旋判断发现是STOP,不管任务队列是否为空直接rerurn null后,线程自然结束。 |
| 刚获取任务 | 正常执行该任务 | 中断线程,任务可能执行也可能不执行,任务可能继续执行,取决于是否响应中断,不是"完成后退出",而是任务执行完后检测到 STOP 状态退出,如果任务不响应中断,会一直执行到完成(可能无限循环) |
| 新提交任务 | 拒绝(抛出异常) | 拒绝(抛出异常) |
| 线程池状态 | SHUTDOWN | STOP |
public class ThreadCreateTest extends Thread {
@Override
public void run() {
// 逻辑
}
}
全参构造函数参数介绍,在Java中创建线程池常用的类是ThreadPoolExecutor,该类的全参构造函数如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
while(true){
// 1,预期值X
// 2,要修改的新值Y
if(CompareAndSet(X,Y)){
break;
}
}
读写锁用的是同一个 Sycn 同步器,因此等待队列、state 等也是同一个,写锁状态占了 state 的低 16 位,而读锁使用的是 state 的高 16 位;(state是int类型,占4个字节,4*8 = 32位)。
WriteLock的lock()方法:
public void lock() {
sync.acquire(1);
}
信号量,用来限制能同时访问共享资源的线程上限,就好像ReentrantLock只允许一个线程进去,而Semaphore最多只允许n个线程进去,常用于资源访问,服务限流(Hystrix里限流就有基于信号量方式)
public class SemaphoreRunner {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2);
for (int i=0;i<5;i++){
new Task(semaphore,"zyh"+i).start();
}
}
static class Task extends Thread{
Semaphore semaphore;
public Task(Semaphore semaphore,String tname){
this.semaphore = semaphore;
this.setName(tname);
}
public void run() {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+":aquire():"+System.currentTimeMillis());
Thread.sleep(1000);
semaphore.release();
System.out.println(Thread.currentThread().getName()+":release():"+System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
作用:CountDownLatch类能够使一个线程等待其他线程完成各自的工作后再执行。
使用场景:Zookeeper分布式锁,Jmeter模拟高并发等。
工作原理:CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,通过调用``countDown();`方法使计数器的值就会减1,当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
public class CountDownLatchTest {
private static CountDownLatch countDownLatsh = new CountDownLatch(5);
private static class Player implements Runnable{
private Integer index;
public Player(Integer index){
this.index = index;
}
@Override
public void run() {
System.out.println("玩家"+index+"准备完成");
countDownLatsh.countDown();
}
}
public static void main(String[] args) throws InterruptedException {
for(int i = 0; i < 5; i++){
new Thread(new Player(i)).start();
}
countDownLatsh.await();
System.out.println("玩家准备完毕,开始游戏");
}
}
Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。每个JVM 的实现都要遵守JMM规范,JMM规范的保障了并发程序运行在不同的虚拟机上时,得到的程序结果是安全可靠的。如果没有JMM内存模型来规范,就可能会出现,经过不同 JVM 翻译之后,运行的结果不相同也不正确的情况。
java运行时内存模型JVM运行程序的实体是线程,在每个线程创建时,JVM都会为其创建一个工作内存(有些地方称为栈空间),用于存储线程私有的数据。Java 内存模型JMM规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行。工作内存是线程私有,所以不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成。