1. 线程
1.1. 线程概念
线程是系统运行的最小单位,一个进程由多个线程组成
线程分为:用户线程、守护线程(守护会在所有用户线程销毁后销毁,只要还有一个用户线程存在,那么守护线程也会存在)
1.2. 线程状态
NEW(新建)、RUNNABLE(运行中)、BLOCKED(阻塞)、WAITING(等待)、TIMED_WAITING(有时间的等待)
它们间的运行交互,如下图所示
1.3. 线程的实现方式
实现类或接口 | 重新方法 | 有无返回值 |
继承Thead | run() | 无返回值 |
实现Runnable | run() | 无返回值 |
实现Callable | call() | 有返回值 |
class Thead1 extends Thread{
@Override
public void run() {
super.run();
}
}
class Thead2 implements Runnable{
@Override
public void run() {
}
}
class Thead3 implements Callable {
@Override
public Object call() throws Exception {
return null;
}
}
1.4. 线程的级别
线程也存在级别,分别为1-10的数字,10为最大权限
在真实运行中级别是10的线程,会有较大概率获得CPU和资源,并不所有任务都是它运行
1.5. 线程安全集合
Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、ConcurrentHashMap
2. 锁
2.1. 锁的类型
线程需要锁对共享的资源进行管控,避免出数据错乱
锁类 | 范围 | 显/隐式锁(需不需要手动解锁) |
synchronize | 变量、方法接口和代码块 | 隐式锁 |
ReentrantLock | 代码块 | 显式锁 |
ReentrantReadWriteLock | 代码块 | 显式锁 |
2.2. 公平锁/非公平锁
公平锁是指多个线程尽可能的平均分配CPU资源,非公平锁就是谁抢到CUP就可以运行
synchronize是默认非公平锁
ReentrantLock、ReentrantReadWriteLock是初始化时可以选择公平和非公平锁,默认是非公平锁
2.3. 辅助类
CountDownLatch、CyclicBarrier、Semaphore
3. 线程池
3.1. 线程池初始化
线程的使用,必须使用线程池
线程的创建和销毁是需要消耗资源的,影响系统性能
线程的需要控制数量,线程过多可能导致内存溢出
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}
参数 | ||
corePoolSize | 正常存活的线程数 | 一开就创建的线程数 |
maximumPoolSize | 最大线程数 | 额外新建的最大线程数 |
keepAliveTime | 存活时间 | 是指另外新创建的线程存活时间 |
TimeUnit | 时间单位 | |
BlockingDeque | 阻塞等待队列 | 存最大线程数外的任务队列 |
ThreadFactory | 生产工厂 | |
RejectedExecutionHandler | 拒绝策略 | AbortPolicy(队列满了抛出异常) DiscardPolicy(队列满了丢弃任务不处理) DiscardOldestPolicy(队列满了丢弃最早的任务) CallerRunsPolicy(返回给调用者处理) |
3.2. 线程池的处理逻辑
比如构建一个线程正常存活数为2,最大线程数为5,队列长度为4的线程,处理10个任务
那么它的任务1、2会先处理,之后3、4、5、6会进入队列保存,任务7、8、9线程池会开出新的线程进行处理,而任务10就会执行拒绝策略处理掉
public static void main(String[] args) {
ThreadPoolExecutor threadPool3 = new ThreadPoolExecutor(2,5,3L, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(4), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 1; i <= 10; i++) {
int finalI = i;
threadPool3.execute(new Thread(
()->{
System.out.println(Thread.currentThread().getName() + "开始---" + finalI);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
})
);
}
}finally {
threadPool3.shutdown();
}
}