线程池-阻塞队列

blockingQueue
队列先入先出
阻塞体现在两方面
入队时:如果队列空间已满,数据不会消失,等到空间有容纳余地才会入队
出队时:取数据如果队列中没有数据可取,则会等到有入队数据才可以取出

public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> bq = new LinkedBlockingDeque<>(3);//容量为3的阻塞队列
        bq.add("aaa");
        bq.add("bbb");
        bq.add("ccc");
        System.out.println(bq.peek());
        bq.offer("ddd",3, TimeUnit.SECONDS); //会在队列外等待三秒
        System.out.println(bq.size());
    }

线程池-阻塞队列_第1张图片
线程池-阻塞队列_第2张图片

总结:BlockingQueue继承Queue,Queue继承自Collection
所以Collection最基础的增删改查操作是有的,在这个基础上,多了Queue的特点,在这个基础上又多了阻塞的特点,最终形成了BlockingQueue

常用API

线程池-阻塞队列_第3张图片

线程池工作原理

目的:提高效率,有一些线程始终是活跃的,执行任务时直接拿来用就可以了。省去了出生就绪 和死亡的时间
线程池-阻塞队列_第4张图片

public static void main(String[] args) throws InterruptedException {

        //核心线程:1 最大线程:2  等待时间:0秒 队列容量:3
        //执行的线程任务如果超过核心线程数量则会进入到阻塞队列中等待。
        // 等待的线程数量如果大于队列容量则会创建新的线程来执行任务
        // 此时如果线程任务继续增加,继续生成新的线程。直到核心线程+新线程数量>最大线程数量 报错,拒绝执行
        ThreadPoolExecutor t = new ThreadPoolExecutor(1,2,0,TimeUnit.SECONDS,new LinkedBlockingDeque<>(3));
        t.execute(new MyThread());//执行任务

        t.execute(new MyThread());
        t.execute(new MyThread());
        t.execute(new MyThread());

        t.execute(new MyThread());//可能超过队列容量,会产生新线程,新线程和核心线程分摊任务

        t.execute(new MyThread());//此时再创建,会再产生新线程,大于最大线程数。程序报错

        t.shutdown();//关闭线程池
    }
    static class MyThread implements Runnable{

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"在执行任务");
        }
    }

定长线程池

用池中线程执行任务,一次可执行多个任务(根据线程池中核心线程数量),如果任务多于核心线程数量会进入到阻塞队列中等待(需要先设置休眠时间),然后空闲的线程直接去队列中取任务

public class Test02 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService es = Executors.newFixedThreadPool(3);//定长线程。固定的是核心线程数量
        //执行继承runnable或thread线程的时候调用的是execute方法
        //执行集成callable线程的时候调用submit方法
        List<Future<String>> l = new ArrayList<>(10);
        for (int i = 0; i < 100; i++) {
            Future<String> f = es.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    Thread.sleep(2000);
                    return Thread.currentThread().getName();
                }
            });
            //此时核心线程数有三个,多出来的任务在队列中等待着。核心线程直接去队列中取任务执行,所以一次执行三个
            l.add(f); //把执行结果放到list集合中
        }
        for (Future<String> stringFuture : l) {
            String s = stringFuture.get();
            System.out.println(s);
        }
        es.shutdown();

你可能感兴趣的:(java)