四种方式创建线程
1.通过Thread类创建线程
Thread01 thread = new Thread01();
thread.start();
2.通过实现Runnable接口
Runable01 runable01 = new Runable01();
new Thread(runable01).start();
3.通过实现Callable接口 + FutureTask 实现 ,可以拿到返回值
FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
new Thread(futureTask).start();
//阻塞等待线程执行完拿到返回值
Integer integer = futureTask.get();
4.通过线程池实现
我们以后在业务代码里面,以上三种启动线程的方式都不用,将所有多线程的异步任务都交给线程池来实现
固定线程数量大小的线程池
区别:1,2不能得到返回值,3可以得到返回值
1,2,3都不能控制资源
4可以控制资源
ExecutorService service = Executors.newFixedThreadPool(10);
service.execute(()->{})
//原生线程池
//7大参数
corePoolSize:核心线程数;线程池创建好以后就准备就绪的线程数量,就等待来接收异步任务去执行。
maximumPoolSize:最大线程数量,控制资源
keepAliveTime:存活时间,当前正在运行的线程数量大于核心数量,
unit:时间单位
BlockingQueue<Runnable> workQueue 阻塞队列,如果任务有很多,就会将目前多的任务放到阻塞队列里面,线程有空闲,就会去队列里面取新的任务继续执行
threadFactory:线程创建的工程
RejectedExecutionHandler handler:如果队列满了,按照我们指定的拒绝策略拒绝执行任务
ThreadPoolExecutor pool = new ThreadPoolExecutor();
1.线程池创建,准备好core数量的核心线程,准备接受任务
2.新的任务进来,用core准备好的空闲线程执行
1>core满了,就将再进来的任务放入阻塞队列中。空闲的core就会自己去阻塞队列获取任务执行
2>阻塞队列满了,就直接开新线程执行,最大只能开到max指定的数量
3>max都执行好了,max-core的数量空闲的线程会在keepAliveTime指定的时间后自动销毁。最终保持到core大小
3.所有线程都由线程池创建
工作顺序
1)线程池创建,准备好core数量的核心线程,准备接受任务。
2)core满了,就将新进来的任务放入阻塞队列中,空闲的core就会自己去阻塞队列获取任务执行
3)阻塞队列满了,就直接开新线程,最大只能开到 max指定的数量
4)max满了就调用RejectedExecutionHandler执行拒绝任务
5)max都执行好了,max-core的数量空闲的线程会在keepAliveTime指定的时间后自动销毁。最终保持到core大小
new LinkedBlockingDeque<>():默认是Integer最大值,内存不够
面试题:一个线程池 core 7 max20 queue 50 ,100个并发任务是怎么分配的
core 进7个立即执行
队列里面放进50个
再开13个新线程执行
剩下30个使用拒绝策略执行
Executors.newCachedThreadPool() core是0.所有都可回收
newFixedThreadPool() 固定大小,core =max,都不可回收
newScheduledThreadPool() 定时任务的线程池
newSingleThreadPool() 单线程线程池
开发中为什么要是有线程池
1.降低资源的消耗
2.提高响应速度
3.提高线程的可管理性
在业务复杂的情况下,一个异步调用可能会依赖于另一个异步调用的执行结果。
Future是java5添加的类,用来描述一个异步计算的结果,可以使用isDone方法检查计算
网友评论