欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

蓝桥杯Java课程学习——多线程(二)

程序员文章站 2022-06-26 13:28:43
...



ArrayBlockingQueue

ArrayBlockingQueue 是由数组支持的有界阻塞队列。位于 java.util.concurrent包下。

构造方法

构造方法 描述
public ArrayBlockingQueue(int capacity) 构造大小为 capacity 的队列
public ArrayBlockingQueue(int capacity, boolean fair) 指定队列大小,以及内部实现是公平锁还是非公平锁
public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) 指定队列大小,以及锁实现,并且在初始化是加入集合 c

入队常用方法

入队方法 队列已满 队列未满
add 抛出异常 返回 true
offer 返回 false 返回 true
put 阻塞直到插入 没有返回值

出队常用方法

出队方法 队列为空 队列不为空
remove 抛出异常 移出并返回队首
poll 返回 null 移出并返回队首
take 阻塞直到返回 移出并返回队首

实例

import java.util.concurrent.ArrayBlockingQueue;

public class ABQDemo {
    //构建大小为10的阻塞队列
    private static ArrayBlockingQueue<Integer> arrayBlockingQueue = new ArrayBlockingQueue<>(10);

    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                arrayBlockingQueue.add(i);
            }
        });
        thread1.start();
        try {
            //等待线程1执行完毕
            thread1.join();	//将线程的并行执行改为串行执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        new Thread(() -> {
            //如果插入失败
            if (!arrayBlockingQueue.offer(11)) {
                System.out.println("插入元素11失败");
            }
            try {
                //一直阻塞直到插入元素11,注意这里阻塞的不是主线程,main方法还是继续运行
                arrayBlockingQueue.put(11);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }).start();



        Thread thread2=new Thread(() -> {
            Integer element;
            System.out.println("开始出队:");
            //打印队列中的元素
            while ((element = arrayBlockingQueue.poll()) != null) {
                System.out.print("\t"+element);
            }
        });
        thread2.start();
    }
}

消费者生产者模型

import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;

public class PCModel {
    //阻塞队列
    private static LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();

    public static void main(String[] args) {
        //生产者
        Thread provider = new Thread(() -> {
            Random random = new Random();
            for (int j = 0; j < 5; j++) {
                try {
                    int i = random.nextInt();
                    //注释直到插入数据
                    queue.put(i);
                    System.out.println("生产数据:" + i);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //消费者
        Thread consumer = new Thread(() -> {
            Integer data;
            for (int i = 0; i < 5; i++) {
                try {
                    //阻塞直到取出数据
                    data = queue.take();
                    System.out.println("消费数据:" + data);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //启动线程
        provider.start();
        consumer.start();
    }
}

线程池

线程池(英语:thread pool):一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。

由于 Java 创建和销毁线程都会带来资源上的销毁,所以线程池可以帮助我们复用线程,减少资源消耗。

创建线程池

1、Java 线程池可以通过Executors工具类创建,Executors 常用方法:

  • newFixedThreadPool(int nThreads): 创建一个固定大小为 n 的线程池
  • newSingleThreadExecutor(): 创建只有一个线程的线程池
  • newCachedThreadPool(): 创建一个根据需要创建新线程的线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolDemo {
    //使用Executors 创建一个固定大小为5的线程池
    private static ExecutorService executorService = Executors.newFixedThreadPool(5);

    public static void main(String[] args) {
//        提交任务
        executorService.submit(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.print(i + " ");
            }
        });
        //停止线程池 并不会立即关闭 ,而是在线程池中的任务执行完毕后才关闭
        executorService.shutdown();
    }
}

2、直接创建线程池,ThreadPoolExecutor

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolDemo2 {
    private static ExecutorService executorService = new ThreadPoolExecutor(
            5, //核心线程数为5
            10,//最大线程数为10
            0L, TimeUnit.MILLISECONDS,//非核心线程存活时间
            new LinkedBlockingQueue<>());//任务队列

    public static void main(String[] args) {
        //提交任务
        executorService.submit(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.print(i + " ");
            }
        });
        //关闭线程池
        executorService.shutdown();
    }
}