并发容器与线程池

一、容器分类

  • Collection是一个个元素的加到容器;
  • Map是一对对元素的加入容器;
  • Queue主要是为高并发提高服务;

物理上只有两种分类:连续存储的数组 + 非连续存储的链表

请添加图片描述
Vector、HashTable是最早期的容器,每个方法都自带Sychronized,基本不用,只需要了解其数据结构;

Map高并发时使用ConcurrentHashMap主要是因为它读取数据的速度快,插入数据的速度未必会比HashTable、SychronizedHashMap快;
(发展历程:HashTable — HashMap — SynchronizedMap — ConcurrentHashMap)

Collection高并发时用Queue,可以保证线程安全同时效率高,要保证元素的一致性,可以使用Set里的同步Set数据结构;
(发展历程:Vector — List/Set — Queue)

二、Queue

与List的区别主要是添加了许多对多线程友好的api(offer、peek、poll、put、take)

  • BlockingQueue:在queue的接口方法上添加了两个方法put和take在队列满了和空了时会阻塞(add/remove方法会报异常,offer/poll不报异常但会退出程序),底层用LockSupport的park和unpark实现了Condition.await()方法导致阻塞(生产者消费者模型);

  • ArrayBlockingQueue:有界数组式阻塞队列;

  • LinkedBlockingQueue:链式阻塞队列;

  • PriorityQueue:小顶堆排序,根据加入的元素的大小从小到大输出,不是按照加入时间的先后输出;

  • DelayQueue:按照加入时设置的定时时间先后输出;

  • SynchronousQueue:一个线程先执行queue.take()并阻塞,当另一个线程执行queue.put()时阻塞线程会拿到该数据并不再阻塞,但是该queue中始终不能存放对象,仅仅作为两个线程传递数据的手段

  • TransferQueue:多个线程等待其他线程来传输对象,队列可以支持多个线程之间传递数据,而SynchronousQueue只能支持两个线程之间传递数据;

三、线程池

  • Runnable:定义线程执行任务的接口;(接口)
  • Callable = Runnable + return:在Runnable的基础上增加了一个执行完任务后将来会返回的一个结果值;(接口)
  • Future:存放Callable接口中将来返回的结果值;(接口)
  • FutureTask = Future + Runnable:可以执行任务并将任务的返回结果存放在对象自身上;(类)

Callable可以执行一个带返回值的任务,但是他的返回值需要存储在Future中,而FutureTask实现了Runnable和Future,所以他可以执行一个带返回值的任务,并将返回值存在自己的对象中,future执行任务的线程和主线程是异步的,但是主线程从future中获取返回值是同步阻塞的

public class FutureTaskDemo {
    public static void main(String[] args) {
        FutureTask<String> ft = new FutureTask<>(()->{
            return "future task";
        });
        /** 起一个线程异步执行future任务 */
        new Thread(ft).start();

        try {
            /** 从Future中获取返回值的操作是阻塞的 */
            System.out.println(ft.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

线程池分类

  • ThreadPoolExecutor:普通线程池;(一个任务队列)
  • ForkJoinPool:将总任务分解成多片执行然后再汇总;(多个任务队列)
  • WorkStealingPool:每一个线程有自己的一个任务队列,当一个线程任务队列空了后,可以从其他线程的队列中拿任务来执行;

七大参数

  • 核心线程数
  • 最大线程数
  • 线程空闲存活时间(大于核心线程数的线程会被OS回收)
  • 空闲时间单位
  • 任务阻塞队列
  • 线程工厂
  • 拒绝策略:JDK默认提供了四种,但是这是可以自定义的,所以准确的说没有具体上限(实际中都是自定义的处理策略,一般会把没处理的任务丢到消息队列或者数据库,然后用日志记录还有哪些任务没被处理)

默认的线程池

  • SingleThreadExecutor:只有一个线程,保证顺序执行任务;
    为什么不直接new一个线程?——线程池有任务队列,有生命周期管理;

  • CachedThreadPool:核心线程数为0,最大线程数为Integer.MAX_VALUE,线程存活时间为0,任务队列为SynchronousQueue也就是说有一个任务来了必须有一个线程来执行,不能放到队列里

  • FixedThreadPool:固定线程数量,核心线程和最大线程都是一样的一个固定的值;具体使用多少线程数可以结合压力测试用一个经验公式计算;

  • ScheduledThreadPool:用来执行定时任务的线程池,任务队列使用的是DelayedWorkQueue,加入的任务都带有一个延迟执行的时间,时间到了用一个线程去执行;

note:用线程池应对亿级流量:先将流量分发到多个边缘服务器,每个服务器中存有的并发量仍然很高,用线程池加消息队列解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值