线程
创建线程的三种方式
- 1、继承Thread类,重写run方法
- 2、实现Runnable接口
- 3、使用Executor Service、Callable、Future实现有返回结果的多线程
线程的状态
- 就绪 Runnable: 线程准备运行
- 运行中 Running : 进程正在执行线程中的代码
- 等待中 Waiting : 线程处于阻塞状态,等待外部处理结束
- 睡眠中 Sleeping : 线程被强制睡眠
- I/O阻塞
- 同步阻塞 Blocked on Synchronized :等待获取锁
- 死亡 Dead:线程完成了执行
死锁
两个进程都在等待对象执行完成才能往下继续执行就发生了死锁,结果就是两个进程都陷入了无限的等待中。
如何确保N个线程可以访问N个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁,因此,如果所有的线程都是以同样的顺序枷锁和释放锁,就不会出现死锁了。
多线程
线程是程序的执行路径,也可以说是程序的控制单元
一个进程可能包含多个线程,当一个进程存在多条执行路径时,就可以将该执行方式称为多线程。
线程的执行方式大致为就绪,运行,等待,阻塞,死亡 这些i状态的转换实质上是在抢夺CPU资源过程中造成的,正常情况下cpu资源不会被线程独自占用,因此多个线程在运行中相互争夺资源,造成线程在上述几个状态之间不断的相互转换,这也是多线程的执行方式
线程池
池化思想(提高资源利用率):线程池、字符串常量池、数据库连接池
[作用]:
- 提高线程的利用率
- 提高程序的响应速度
- 便于统一管理线程
- 控制并发数量
工作原理
概念:核心线程数、最大线程数、等待队列、拒绝策略、线程存活时间、时间单位
任务进来 创建线程数,当核心线程全部创建完,任务进入等待队列,等待队列满,创建临时线程
public static void main(String[] args) {
// 核心线程数、最大线程数、存活时间、时间单位、等待队列、线程工厂、拒绝策略
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 9; i++) {
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName() + "===>办理业务");
});
}
threadPoolExecutor.shutdown();
}
阻塞队列
BlockingQueue 阻塞队列类似于生产者/消费者模式
往队列中put数据,循环判断:如果队列满了,put阻塞,唤醒take
从队列中take数据,循环判断:如果队列中没有数据,take阻塞,唤醒put
- ArrayBlockingQueue ---- 基于数组的阻塞队列
- LinkedBlockingDeque ---- 基于链表的阻塞队列
拒绝策略
-
new ThreadPoolExecutor.AbortPolicy() ---- 终止异常,程序抛出异常
-
new ThreadPoolExecutor.DiscardOldestPolicy() ---- 抛弃策略,抛弃最旧未处理的任务
-
new ThreadPoolExecutor.DiscardPolicy() ---- 抛弃策略,抛弃最新进来的任务
-
new ThreadPoolExecutor.CallerRunsPolicy() ---- 让主线程执行改任务,

浙公网安备 33010602011771号