JUC-阻塞队列+线程池

文章目录

  • BlockingQueue
    • 概念
    • 四组API
  • SynchronousQueue同步队列
    • 代码
  • 线程池
    • 池化技术
    • 线程池创建
      • 三大方法
      • 七大参数
      • 业务图原理
      • 四大拒绝策略
      • 最大线程池设置
    • 向线程池提交任务
      • 1. execute
      • 2. submit
  • A

BlockingQueue

概念

  1. 阻塞
    JUC-阻塞队列+线程池_第1张图片
  2. 队列间关系
    JUC-阻塞队列+线程池_第2张图片
  3. 使用阻塞队列的场景

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

四组API

方式 抛出异常 有返回值 阻塞等待 超时等待
添加 add offer put offer(,)
移除 remove poll take poll(,)
检测队列首 element peek
  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. 阿里巴巴手册
    JUC-阻塞队列+线程池_第3张图片

三大方法

// 本质都是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) // 拒绝策略

业务图原理

JUC-阻塞队列+线程池_第4张图片

四大拒绝策略

  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

你可能感兴趣的:(JUC)