什么是多线程
在一个程序中同时执行多个线程,每个线程可以独立地执行不同的任务或操作
多线程的优缺点
优点
多线程处理可以同时运行多个线程
。由于多线程应用程序将程序划分成多个独立的任务,因此可以在以下方面显著提高性能
- 多线程技术使程序的
响应速度更快
,因为用户界面可以在进行其它工作的同时一直处于活动状态; - 当前没有进行处理的任务时可以将处理器时间
让给其它任务
; - 占用大量处理时间的任务可以定期将处理器时间
让给其它任务
; - 可以
随时停止任务
; - 可以分别
设置
各个任务的优先级
以优化性能
缺点
- 线程也是程序,所以线程需要占用内存,
线程越多占用内存也越多
; - 多线程
需要协调和管理
,所以需要CPU时间跟踪线程; - 线程之间对共享资源的访问会
相互影响
,必须解决竞用共享资源的问题; - 线程太多会导致
控制太复杂
,最终可能造成很多Bug;
创建线程的四种方式
1.继承Thread类
自定义线程类
继承Thread类
重写run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
2.实现Runnable接口
定义MyRunnable类
实现Runnable接口
实现run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
3.实现Callable接口
实现Callable接口
,需要返回值类型
重写call方法,需要抛出异常 创建目标对象
创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
提交执行:Future result1 = ser.submit(t1);
获取结果:boolean r1 = result1.get()
关闭服务:ser.shutdownNow();
4.使用线程池
使用前提:经常创建和销毁,使用量特别大的资源时,比如并发情况下的线程,对性能影响很大
使用方式:提前创建多个线程
,放入线程池,使用时直接获取,使用完放回池中。可以避免频繁创建销毁,实现重复利用
好处
:
1、提高响应速度(减少了创建新线程的时间)
2、降低资源消耗(重复利用线程池中线程,不需要每次创建)
3、便于线程管理
java中线程的状态
Java中线程的状态分为6种。
初始
(NEW):新创建了一个线程对象,但还没有调用start()方法。运行
(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。阻塞
(BLOCKED):表示线程阻塞于锁。等待
(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。超时等待
(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。终止
(TERMINATED):表示该线程已经执行完毕。
线程池的创建方式
线程池的创建⽅式总共包含以下 7 种(其中 6 种是通过 Executors 创建的,1 种是通过ThreadPoolExecutor 创建的)
1. Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池,可控制并发的线程数,超出的线程会在队列中等待;
2. Executors.newCachedThreadPool:创建⼀个可缓存的线程池,若线程数超过处理所需,缓存⼀段时间后会回收,若线程数不够,则新建线程;
3. Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执⾏顺序;
4. Executors.newScheduledThreadPool:创建⼀个可以执⾏延迟任务的线程池;
5. Executors.newSingleThreadScheduledExecutor:创建⼀个单线程的可以执⾏延迟任务的线程池;
6. Executors.newWorkStealingPool:创建⼀个抢占式执⾏的线程池(任务执⾏顺序不确定)【JDK1.8 添加】。
7. ThreadPoolExecutor:最原始的创建线程池的⽅式,它包含了 7 个参数可供设置,后⾯会详细讲。
线程池等待队列满了解决办法
-
增加线程池的大小
:通过增加线程池的大小,可以缓解等待队列的压力。 -
改变拒绝策略
:线程池的拒绝策略决定了当等待队列满了后,如何处理新的任务。可以通过改变拒绝策略,使得线程池能够更好地处理任务。 -
限制任务数量
:限制任务数量可以防止等待队列过于拥挤。 -
使用另一个线程池
:如果当前的线程池无法满足需求,可以考虑使用另一个线程池。