多线程简介
一、线程与进程
- 1.进程:系统中运行的程序,一个进程至少有一个线程
- 2.线程:进程的基本执行单元
二、多线程原理
每个CPU实际只能处理一条线程,多线程实际是CPU在多个线程之间来回切换,由于时间特别快,给人造成并行执行的假象;一个进程中有多个线程执行任务可以提高程序效率;
三、多线程实现的4种方式
- extends Thread:不灵活
- implements Runable:工作中常用
- implements Callable<Object.class>:可以有返回值
- 4种线程池的方式创建多线程:
Executors.newFixedThreadPool():定长线程池
Executors.newCachedThreadPool():不定长线程池
Executors.newSingleThreadExecutor();单线程池
Executos.newScheduledThreadPool();定长可调度线程池:定时,延时等功能;
四、优缺点
- 优点:
能适当的提程序的执行效率
能适当的提高资源的使用率
线程执行完所有任务后自动销毁 - 缺点:
开启线程需要占用一定的内存空间(默认情况下,每一个线程都占512KB)
如果开启大量的线程,会占用大量的内存空间,降低程序的性能
线程越多,cpu在调用线程上的开销就越大
程序设计更加复杂,比如线程间的通信、多线程的数据共享
五、多线程的应用场景
1、为什么要使用多线程:
- 1.单线程代码执行的顺序是从上到下,如果中间的某个环境一旦出现错误,整个程序会直接中断;某些代码执行时间过长,接口等待时间太长,造成请求被超时拦截中断;
- 2.多线程采用多条不同的线程执行我们的代码程序,相互之间互不影响,可以提高程序的效率;
2、多线程的应用场景
- 异步的实现短信发送
- 异步的记录日志
- 对后端接口中耗时比较长的任务(比如读取文件、调用其它的任务、外部接口回调响应等),影响响应时间的都可以采用异步实现
- 后台任务:比如大量的订单归档,发送短信等
- 分布式计算
六、配置原则
1.计算密集型:每个线程的处理时间比较短,线程可以复用;故少配置线程,
以减少CPU的频繁切换对性能带来的影响;
一般情况下:线程数cpu核数
2.IO密集型:每个线程处理时间较长,线程难以复用;故需要多配置线程;
一般情况下:线程数2*cpu核数
3.计算出程序所需的线程数:
首先我们要明白一个概念叫 阻塞系数
如果任务有50%的时间处于阻塞状态,则阻塞系数为0.5。则程序所需的线程数为处理器可用核心数的两倍。如果任务被阻塞的时间少于50%,即这些任务是计算密集型的,则程序所需线程数将随之减少,但最少也不应该低于处理器的核心数。如果任务被阻塞的时间大于执行时间,即该任务是IO密集型的,我们就需要创建比处理器核心数大几倍数量的线程。
程序所需线程的总数,总结如下:
线程数 = CPU可用核心数/(1 - 阻塞系数),其中阻塞系数的取值在0和1之间。
计算密集型任务的阻塞系数为0,而IO密集型任务的阻塞系数则接近1