这里是目录
- 线程和进程的区别
- 多线程的几个对象
- 线程池
- 线程间的同步的方式
线程和进程的区别
- 进程是一个程序执行一次创建的,是系统运行程序的基本单位。
- 线程是⼀个⽐进程更⼩的执⾏单位,一个进程在运行期间可以产生多个线程。多个线程可以共享进程的堆和⽅法区资源,每个线程有⾃⼰的程序计数器、虚拟机栈和本地⽅法栈。
- 线程是进程划分成的更⼩的运⾏单位。
- 线程和进程最⼤的不同在于基本上各进程是独⽴的,⽽各线程则可以有共享的资源也有自己独有的资源。
- 线程执⾏开销⼩,但不利于资源的管理和保护;⽽进程正相反
多线程的几个对象
- 任务对象
- Runable
- 核心方法run方法
- 需要通过executor的execute方法执行
- Callable:
- 核心方法 call方法
- 需要通过executor的submit方法执行
- Runable
- 执行对象
- executor:顶层接口,包含execute方法
- ExecutorService:继承executor接口,包含submit和shutdown方法
- 结果
- Future:线程返回结果的顶层接口,包含get方法
- FutureTask是Future的实现类
线程池
-
ThreadPoolExecutor
- 核心参数
- 核心线程数
- 最大线程数
- 等待队列最大长度
- Executors工具类实现的线程池
- FixedThreadPool:固定线程数,使用无界等待队列,大量任务堆积等待队列中会出现OOM
- SingleThreadExecutor:线程池只有一个线程,使用无界等待队列,大量任务堆积等待队列中会出现OOM
- CachedThreadPool:使用的同步队列,不存储等待任务,只要任务进来,就创建线程执行任务,且允许创建的线程数量为 Integer.MAX_VALUE,会出现OOM
- ScheduledThreadPool:使用的无界的延迟阻塞队列,内容使用的最小堆排列,同样大量任务堆积等待队列中会出现OOM
- 线程池的拒绝策略
- 抛出异常之后拒绝任务
- 将任务回退给调用者,使用调用者的线程来执行任务
- 直接丢弃掉
- 丢弃等待队列中的最早进来的未处理的任务请求
- 线程池中任务进来的判断流程
- 可以看出是先判断等待队列是否可以放入,才判断是否是小于最大线程数,然后创建线程
- 核心参数
-
线程池创建核心参数设置
- 计算密集型
- 可以将线程数设置为 N(CPU 核心数)+1
- IO密集型
- 设置最大进程数为2N
- 计算密集型
-
线程池尽量不要放耗时任务
- 线程池本身的目的是为了提高任务执行效率,避免因频繁创建和销毁线程而带来的性能开销。如果将耗时任务提交到线程池中执行,可能会导致线程池中的线程被长时间占用,无法及时响应其他任务,甚至会导致线程池崩溃或者程序假死。
线程间的同步的方式
- 互斥:只有拿到互斥对象的线程才能访问资源
- 信号量:允许多个线程访问资源,当时线程数必须在信号量允许的范围内
- 事件:通过事件通知的方式实现线程同步。