JUC-阻塞队列+线程池

BlockingQueue

概念

  1. 阻塞
    在这里插入图片描述
  2. 队列间关系
    在这里插入图片描述
  3. 使用阻塞队列的场景

多线程并发处理,线程池!

四组API

方式抛出异常有返回值阻塞等待超时等待
添加addofferputoffer(,)
移除removepolltakepoll(,)
检测队列首elementpeek
  1. 抛出异常
/**
 * 抛出异常
 */
public static void test01(){
    //队列的大小,即最多放多少个数据
    ArrayBlockingQueue queue = new ArrayBlockingQueue(3);
    System.out.println(queue.add("a"));
    System.out.println(queue.add("b"));
    System.out.println(queue.add("c"));
    //java.lang.IllegalStateException: Queue full 抛出异常!
    System.out.println(queue.add("d"));

    System.out.println("===============");
    System.out.println(queue.remove());
    System.out.println(queue.remove());
    System.out.println(queue.remove());
    //java.util.NoSuchElementException 抛出异常!
    System.out.println(queue.remove());
}
  1. 不会抛出异常
/**
 * 有返回值,没有异常
 */
public static void test02(){
    //队列的大小,即最多放多少个数据
    ArrayBlockingQueue queue = new ArrayBlockingQueue(3);

    System.out.println(queue.offer("a"));
    System.out.println(queue.offer("b"));
    System.out.println(queue.offer("c"));
    //false 不抛出异常!
    System.out.println(queue.offer("d"));

    System.out.println("===============");
    System.out.println(queue.poll());
    System.out.println(queue.poll());
    System.out.println(queue.poll());
    //null 不抛出异常!
    System.out.println(queue.poll());
}
  1. 阻塞 等待
/**
 * 等待,阻塞(一直阻塞)
 */
public static void test03() throws InterruptedException {
    //队列的大小,即最多放多少个数据
    ArrayBlockingQueue queue = new ArrayBlockingQueue(3);

    //无返回值,一直阻塞
    queue.put("a");
    queue.put("b");
    queue.put("c");
    //队列没有位置了,线程会一直等待
    queue.put("d");

    System.out.println(queue.take());
    System.out.println(queue.take());
    System.out.println(queue.take());
    //没有这个元素,线程会一直等待
    System.out.println(queue.take());
}
  1. 超时等待
/**
 * 等待,阻塞(超时等待)
 */
public static void test04() throws InterruptedException {
    //队列的大小,即最多放多少个数据
    ArrayBlockingQueue queue = new ArrayBlockingQueue(3);

    queue.offer("a",10L, TimeUnit.SECONDS);
    queue.offer("b",10L, TimeUnit.SECONDS);
    queue.offer("c",10L, TimeUnit.SECONDS);
    //等待超过5秒就退出
   queue.offer("d",5L, TimeUnit.SECONDS);

    System.out.println(queue.poll());
    System.out.println(queue.poll());
    System.out.println(queue.poll());
    //等待超过2秒就退出
    System.out.println(queue.poll(2L,TimeUnit.SECONDS));
}

SynchronousQueue同步队列

代码

/**
 * 同步队列
 * 和其他的BlockingQueue 不一样, synchronousQueue 不存储元素
 * 即 put了一个元素,必须从里面先take取出来,否则不能再put进去
 */
BlockingQueue<String> synchronousQueue = new SynchronousQueue<>();

new Thread(()->{
    try {
        synchronousQueue.put("1");
        synchronousQueue.put("2");
        synchronousQueue.put("3");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

new Thread(()->{
    try {
        TimeUnit.SECONDS.sleep(3L);
        System.out.println(synchronousQueue.take());
        TimeUnit.SECONDS.sleep(3L);
        System.out.println(synchronousQueue.take());
        TimeUnit.SECONDS.sleep(3L);
        System.out.println(synchronousQueue.take());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();

线程池

池化技术

  1. 概念

事先准备好一些资源,有人要用,就来这里拿,用完还
线程池、连接池、内存池、对象池…创建、销毁。十分浪费资源

  1. 好处
  1. 降低资源的消耗
  2. 提高响应的速度
  3. 方便管理
  1. 线程复用,可以控制最大并发数、管理线程

线程池创建

  1. 阿里巴巴手册
    在这里插入图片描述

三大方法

// 本质都是threadPoolExecutor
        ExecutorService threadPool =
//        Executors.newSingleThreadExecutor();// 单个线程
//        Executors.newFixedThreadPool(5); // 创建固定的线程池的大小
        Executors.newCachedThreadPool(); // 可伸缩的

七大参数

public ThreadPoolExecutor(int corePoolSize,  //核心线程数量
                          int maximumPoolSize,  //非核心线程数量
                          long keepAliveTime, // 非核心线程保持时长,超时了没有人调用就会释放
                          TimeUnit unit, // 时长单位
                          BlockingQueue<Runnable> workQueue, // 阻塞队列
                          ThreadFactory threadFactory, // 线程工厂(创建线程的,一般不用动)
                          RejectedExecutionHandler handler) // 拒绝策略

业务图原理

在这里插入图片描述

四大拒绝策略

  1. 直接抛出异常(AbortPolicy)

new ThreadPoolExecutor.AbortPolicy()

  1. 哪来的去哪里(如由main线程执行)(CallerRunsPolicy)

new ThreadPoolExecutor.CallerRunsPolicy()

  1. 队列满了,丢弃任务,不会抛出异常(DiscardPolicy)

new ThreadPoolExecutor.DiscardPolicy()

  1. 队列满了,尝试去和最早的竞争,也不会抛出异常(DiscardOldestPolicy)

new ThreadPoolExecutor.DiscardOldestPolicy()

最大线程池设置

  1. CPU 密集型:几核就是几,可以保持CPU的效率最高
    int num = Runtime.getRuntime().availableProcessors();
  2. IO 密集型:判断程序中十分耗IO的程序数量,可为两倍

向线程池提交任务

1. execute

// 没有返回值,直接提交任务( Runnable )
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
pool.execute(new Runnable() {
    @Override
    public void run() {

    }
});

2. submit

// 有返回值,传入的是FutureTask接口实现类
Future<?> submit = pool.submit(new FutureTask<Integer>(new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return 1;
    }
}));

// 通过get获取返回值,若线程还没执行完会先阻塞
try {
    Object o = submit.get();
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

A

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值