多线程与高并发
基础概念
进程
- 是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位
- 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。
- 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元
线程
- 一个进程可以有很多线程,每条线程并行执行不同的任务
- 是操作系统能够进行运算调度的最小单位
创建的不同方式
- 继承 Thread
static class MyRun implements Runnable {
@Override
public void run() {
System.out.println("Hello MyRun!");
}
}
- 实现 Runable,优先选择该方案,因为java是单继承
static class MyRun implements Runnable {
@Override
public void run() {
System.out.println("Hello MyRun!");
}
}
- 实现Callable
static class MyCall implements Callable<String>{
@Override
public String call() throws Exception {
return null;
}
}
- 线程池
启动方式
- 方式1
new MyThread().start();
- 方式2
new Thread(new MyRun()).start();
- 方式3
new Thread(()->{
System.out.println("hello ,Lambda");
}).start();
- 方式4
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(()->{
System.out.println("Hello , thread pool");
});
executorService.shutdown();
方法
- join
- sleep
- yield
- wait(继承Object)
- notify(继承Object)
生命周期
- 开始
新生状态 - 就绪
准备开始执行,并没有执行,调用start之后 - 运行
- 阻塞
阻塞状态,在程序运行过程中,发生某些异常 - 结束
死亡状态
synchronized
- 保证同一时刻最多只有一个线程执行这段代码
- 锁可重入(一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁.)
- 程序中出现异常,默认情况下锁会释放
- 同步方法和非同步方法可同时调用
底层实现
- JDK早期 重量级,需要向操作系统申请
- 改进,锁升级
markwork记录线程id(偏向锁)
如果线程争用,升级为自旋锁
默认在自旋10次之后(JDK1.6),升级为重量级锁;或者在自旋线程超过CPU内核数的一半时,升级为重量级锁。
锁的四种状态
- 无锁
- 偏向锁,适用于单个线程
- CAS(自旋锁),默认自旋10次,适用于并发数少,操作时间短
- 重量级锁(OS),适用于并发数大,操作时间长
锁只能升级,不能降级
无锁 -> 偏向 -> CAS -> 重量
对某个对象加锁
private int count = 10;
private Object o = new Object();
public void m() {
//任何线程要执行下面的代码,必须先拿到o的锁
synchronized(o) {
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
private int count = 10;
public void m() {
//任何线程要执行下面的代码,必须先拿到this的锁
synchronized(this) {
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
}
private int count = 10;
//等同于在方法的代码执行时要synchronized(this)
public synchronized void m() {
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
- 静态方法,锁duXXX.class
public class T {
private static int count = 10;
/**
* 这里等同于synchronized(T.class)
* */
public synchronized static void m() {
count--;
System.out.println(Thread.currentThread().getName() + " count = " + count);
}
public static void mm() {
synchronized(T.class) { //考虑一下这里写synchronized(this)是否可以?
count --;
}
}
}
volatile
- 禁止指令重排序
Double check Lock(单例模式 双重检查)
- 申请内存
- 赋值
- 指定地址
- 保证线程可见性
- MESI,缓存一致性协议
AtomicXXX
原理
CAS
ABA 问题
通过加版本号解决该问题
累加实现
- atomic
- sync
- LongAdder
- 分段锁
- 并发高时效率最高
线程池
ForkJoinPool
ForkJoinPool
ScheduledThreadPool
ScheduledThreadPool
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
System.out.println(System.currentTimeMillis());
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
System.out.println("延迟三秒执行");
System.out.println(System.currentTimeMillis());
}
},3, TimeUnit.SECONDS);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("延迟一秒,没三秒执行一次");
System.out.println(System.currentTimeMillis());
}
},1,3, TimeUnit.SECONDS);
ThreadPoolExecutor
CachedThreadPool
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 20 ; i++) {
executorService.execute(new Task());
}
FixedThreadPool
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 20 ; i++) {
executorService.execute(new Task());
}
SingleThreadPool
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 20 ; i++) {
executorService.execute(new Task());
}
拒绝策略
Exchanger
- 两个线程交换数据,会进入阻塞状态
- exchange()
Semaphore
- new Semaphore(2)
只能同时运行两个,起到限流的作用 - s.acquire() 获取
- s.release() 释放
ReadWriteLock
- readWriteLock.readLock()
- readWriteLock.writeLock()
Phaser
- phase.arriveAndDeregister()
- phase.register()
- phase.bulkRegister(7)
- phaser.arriveAndAwaitAdvance();
CyclicBarrier
new CyclicBarrier(20,new Runnable())
barrier.await()
CountDownLatch
latch.countDown()
latch.await()
原理:CAS
ReentrantLock
tryLock(5,TimeUnit.SECONDS)
lockInterruptibly()
可对interrupt()做出响应
公平锁和非公平锁
原理:CAS