线程的基础知识

线程与进程的区别

image-20250406111500795

image-20250406111536345

image-20250406111657756

并行与并发的区别

image-20250406111905399

image-20250406112003509

线程创建方式

继承Thread类

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyThread extends Thread {
@Override
public void run() {
//TODO
}

public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();
}
}

实现Runnable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyRunnable implements Runnable {
@Override
public void run() {
//TODO
}

public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t1 = new Thread(r);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}

实现Callable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
//TODO
return "ok";
}

public static void main(String[] args) {
MyCallable mc = new MyCallable();
FutureTask<String> ft = new FutureTask<String>(mc);
Thread t1 = new Thread(ft);
t1.start();
String res = ft.get();
System.out.println(res);
}
}

线程池创建线程

1
2
3
4
5
6
7
8
9
10
11
12
public class MyExecutors implements Runnable {
@Override
public void run() {
//TODO
}

public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
threadPool.submit(new MyExecutors());
threadPool.shutdown();
}
}

image-20250406114129768

image-20250406114208190

线程状态

image-20250406114833224

线程顺序执行

image-20250406115154834

Java中的wait和sleep方法的不同

image-20250406115701828

如何停止一个正在运行的线程

image-20250406120902747

线程中并发安全

synchronized原理

image-20250406165846700

Monitor

image-20250406170118476

第二个monitorexit是为了防止同步代码块发生异常时能正常释放锁

image-20250406170726553

每个Java对象都可以关联一个Monitor对象,如果使用synchronized给对象上锁(重量级)后,该对象头的Mark Word中就被设置指向Monitor对象的指针

对象的内存结构

image-20250406171225657

MarkWord

image-20250406171420470

重量级锁

image-20250406172626783

轻量级锁

image-20250406172119649

image-20250406172330935

偏向锁

image-20250406172544499

image-20250406172802178

JMM

Java内存模型(与JVM中的Java内存结构区分)

image-20250406210150166

CAS

image-20250406211214457

image-20250406211556146

image-20250406211725434

乐观锁和悲观锁

image-20250406212538440

volatile

image-20250406213424335

image-20250406213439610

image-20250406214403715

volatile使用技巧:

  • 写变量让volatile修饰的变量在代码最后位置

  • 读变量让volatile修饰的变量在代码最开始位置

AQS

image-20250406214913917

image-20250406215109649

image-20250406215208577

image-20250406215354742

ReentrantLock的实现原理

image-20250406221057199

image-20250406221113721

synchronized和Lock的区别

image-20250406222544943

死锁

互斥

持有且等待

不可剥夺

循环依赖

image-20250406223025879

image-20250406223251118

ConcurrentHashMap

image-20250406223553609

image-20250406223711687

Java如何保证并发安全

image-20250406224029653

  • synchronized:同步加锁

  • JUC提供的lock锁:加锁

image-20250406224155429

image-20250406224304411

线程池

核心参数

image-20250407103044488

image-20250407103217013

常见阻塞队列

image-20250407104424310

image-20250407104311000

如何确定核心线程数

image-20250407104742746

线程池种类

image-20250407105142644

image-20250407105302568

image-20250407105445283

image-20250407105644021

为什么不建议使用Executors创建线程池

image-20250407105805772

使用场景

线程池使用场景

image-20250407110223465

image-20250407111047770

image-20250407111225516

image-20250407111802950

image-20250407112300887

如何控制某个方法允许并发访问线程的数量

image-20250407112451414

image-20250407112732049

ThreadLocal

image-20250407112933479

image-20250407113605930

image-20250407113548377

image-20250407113653653

image-20250407113857553