系列文章目录
文章目录
前言
ConcurrentModificationException
StackOverflowError
OutOfMemoryError
RejectedExecutionException
一、线程、进程?
总结来说:.
进程︰指在系统中正在运行的一个应用程序﹔程序一旦运行就是进程;进程——资源分配的最小单位。·
线程∶系统分配处理器时间资源的基本单元,或者说进程之内独立执行的一个单元执行流。线程——程序执行的最小单位。-
二、Java 的5个状态 ?
- 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
- 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。 - 阻塞(BLOCKED):表示线程阻塞于锁。
- 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
- 终止(TERMINATED):表示该线程已经执行完毕。
三、sleep、wait?
( 1 ) sleep是Thread 的静态方法,wait是 Object的方法,任何对象实例都能调用。-
的尔雅案画A. ,点主三三
( 2 ) sleep不会释放锁,它也不需要占用锁。waitt会释放锁,但调用它的前提是当前线程占有锁(即代码要在synchronized中)。”
( 3)wait 唤醒需要调用 notifyAll notify 而 sleep 会被自动唤醒 设置睡眠时间后
四、串行、并行、并发
串行:
二、volatile
1、volatile java 虚拟机提供的轻量级同步机制
(1),内存可见
(2),禁止指令重排
(3),不保证原子性
三、CAS
CAS并发原语体现在JAVA语言中就是sun.misc.Unsafe类中的各个方法。调用UnSafe类中的CAS方法,JVM会帮我们实现出CASI汇编指令。这是一种完全依赖于硬件的功能,通过它实现了原子操作。再次强调,由于CAS是一种系统原语,原语属于操作系统用语范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。
缺点: 自旋 极端情况 循环比较 开销大 cpu 耗损
List 集合
不安全 :【数组】 ArrayList
安全:【数组】CopyOnWriteArrayList 、Collections.synchronizedList(new ArrayList<>());
不安全:【链表】LinkedList
不安全:【HashMap】HashSet 初始值16 加载因子0.75
读写锁例子:
package com.yang.yimall.order.jmm.list;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 多个线程同时获取一个资源没问题
* <p>
* 写 只能 一个线程来写
*/
public class ReadAndWriteLock {
/**
* 读 - 读 可以
* 读 - 写 不可以
* 写 - 写 不可以
*/
public static void main(String[] args) {
MyCache myCache = new MyCache();
for (int i = 0; i < 5; i++) {
final int temp = i;
new Thread(() -> {
myCache.put(temp + "", temp);
}).start();
}
for (int i = 0; i < 5; i++) {
final int temp = i;
new Thread(() -> {
myCache.get(temp + "");
}).start();
}
}
}
class MyCache {
Map<String, Object> map = new HashMap<>();
static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
void put(String key, Object value) {
lock.writeLock().lock();
map.put(key, value);
try {
System.out.println(Thread.currentThread().getName() + "正在写入.....");
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "正在写入完成");
} catch (Exception e) {
} finally {
lock.writeLock().unlock();
}
}
void get(String key) {
lock.readLock().lock();
map.get(key);
try {
System.out.println(Thread.currentThread().getName() + "正在读取.....");
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + "正在读取完成");
} catch (Exception e) {
} finally {
lock.readLock().lock();
}
}
}
线程池
/**
* 线程池的 7 大参数
* <p>
* corePoolSize 核心线程数:创建好以后准备就绪的线程数量,就等来执行异步任务 ,即使空闲时候也存在 除非设置超时时间
* maximumPoolSize 最大数量:控制数量
* keepAliveTime 存活时间 : maximumPoolSize-corePoolSize 的这部分线程使用后 销毁之前等待下一次消费的时间,
* TimeUnit 时间单位
* BlockingQueue<Runnable> workQueue, 阻塞队列 : n-maximumPoolSize 剩下的任务放在队列里面 ,只要有空闲线程 就回去队列里面拿取任务
* threadFactory : 创建刚工厂 可以默认
* handler : 如果队列满了的按照指定策略处理
*/
/**
* 工作顺序
* 1.1 线程池创建,准备好核心数量线程,准备接受任务
* 1.2 core 满了,就将进来的任务放在阻塞队列里面, 空闲的核心就会 自己去阻塞队列里面获取,执行任务
* 1.3 阻塞队列满了 就直接开启新线程, 只能开到max指定数量
* 1.4 m如果max满了 执行指定拒绝策略
* 1.5 如果max 执行完成有空闲 在指定 keepAliveTime 以后释放 maximumPoolSize-corePoolSize 线程
public static ExecutorService threadExecutor = new ThreadPoolExecutor(
5,
200,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(1000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
*/