进程: 应用程序的执行实例,系统会进行资源分配和调用的独立单位,每一个进程都有自己的内存空间和系统资源
线程:执行运算的最小单位,可完成一个独立的顺序控制流程,CPU调度和分派的基本单位
一个应用程序的运行就可以被看做是一个进程,而线程,是运行中的实际的任务执行者。可以说,进程中包含了多个可以同时运行的线程。
单线程:一个进程只有一条执行路径,就成为单线程程序//参考记事本
多线程:一个线程同时运行多个线程,用来完成不同的工作,多个线程交替占用CPU资源,非真正的并行执行
JAVA提供 Thread
多线程的实现方式:
A 继承Thread类,定义一个MyThread继承Thread类,MyThread类中重写run方法,创建MyThread类的对象,start()启动线程
重写run方法是用来封装被线程执行的代码
run方法和start方法的区别:
a. run()方法封装线程执行的代码,直接调用,相当普通方法的调用,只有主线程一条执行路径
b. start()启动线程,然后由JVM调用此线程的run方法,多条执行路径,主线程和子线程交替运行
B. 实现Runnable接口,定义一个类MyRunnable实现Runnable接口,在MyRunnable中重写run方法,创建MyRunnable类的对象,创建Thread类的对象,把MyRunable类的对象作为构造方法的参数,启动线程
Runnable优势: 避免Java单继承的局限性,适合多个程序的代码去处理同一个资源的情况,把线程和程序的代码,数据有效分离,较好体现了面向对象的思想
Thread类中设置和获取线程名称的方法:
1. void setName(String name): 将此线程的名称改为参数name
2. String getName(): 返回该线程名称
方法1
方法2
currentThread() 返回对当前正在执行的线程对象的引用,属于静态方法
System.out.println(Thread.currentThread().getName());
线程调度
1. 分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
2. 抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些(JAVA使用此模型)
Thread类中设置和获取优先级的方法:
1. public final int getPriority() 返回此线程的优先级
2. public final void setPriority(int newPriority) 更改线程的优先级
线程默认优先级是5,常规优先级范围1——10
线程控制
线程生命周期:
常见的线程安全类型
Arraylist——Vector
HashMap——HashTable(用处不多),ConcurrentHashMap(用处较多)
StringBuilder——StringBuffer
线程池参考下述博客
在一个应用程序中,我们需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。而在Java中,内存资源是及其宝贵的,所以,我们就提出了线程池的概念。
线程池:Java中开辟出了一种管理线程的概念,这个概念叫做线程池,线程池的好处,就是可以方便的管理线程,也可以减少内存的消耗。
Java中已经提供了创建线程池的一个类:Executor,而我们创建时,一般使用它的子类:ThreadPoolExecutor.
Java 多线程:彻底搞懂线程池_孙强 Jimmy 的博客-优快云博客_java多线程线程池
线程池优势
1. 降低资源消耗。通过重复利用已创建的线程,降低线程创建和销毁造成的消耗。
2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
ThreadPoolExecutor最重要的构造方法:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize | 必需 | 核心线程数。默认情况下,核心线程会一直存活,但是当将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收 |
maximumPoolSize | 必需 | 线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。 |
keepAliveTime | 必需 | 线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收 |
unit | 必需 | 指定 keepAliveTime 参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分) |
workQueue | 必需 | 任务队列。通过线程池的 execute() 方法提交的 Runnable 对象将存储在该参数中。其采用阻塞队列实现 |
threadFactory | 可选 | 线程工厂。用于指定为线程池创建新线程的方式 |
handler | 可选 | 拒绝策略。当达到最大线程数时需要执行的饱和策略 |
// 创建线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,
KEEP_ALIVE,TimeUnit.SECONDS,sPoolWorkQueue,sThreadFactory);
// 向线程池提交任务
threadPool.execute(new Runnable() {
@Override
public void run() {
... // 线程执行的任务
}
});
// 关闭线程池
threadPool.shutdown(); // 设置线程池的状态为SHUTDOWN,然后中断所有没有正在执行任务的线程
threadPool.shutdownNow(); // 设置线程池的状态为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表
名称 | 特点 | 应用场景 |
定长线程池(FixedThreadPool) | 只有核心线程,线程数量固定,执行完立即回收,任务队列为链表结构的有界队列 | 控制线程最大并发数 |
周期性执行任务的线程池(ScheduledThreadPool ) | 按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大 | 执行周期性的任务 |
可缓存的线程池(CachedThreadPool) | 该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程 | 执行大量、耗时少的任务 |
单线程化线程池(SingleThreadExecutor) | 只有一条线程来执行任务 | 有顺序的任务 |