Java多线程-3(3)
2021-09-21 17:10
691 查看
8 线程协作(以生产者消费者模型举例)
8.1 生产者消费者模型问题
- 仓库只能存放一件产品,生产者将生产的产品放入仓库,消费者从仓库中产品消费取走
- 若仓库中无产品,生产者将产品存入仓库,否则停止生产并等待至被消费者取走
- 若仓库有产品,消费者消费取走产品,否则停止消费并等待生产者放入产品
producer -> 数据缓冲区 -> consumer
注:synchronized可组织并发更新访问同一共享资源以实现同步,但不能用来实现不同线程之间的消息传递。
8.2 解决方案
注:均为Object类的final方法,只能在同步方法或同步代码块中使用,否则会抛出
IllegalMonitorStateException异常
8.3 解决方法示例(管程法)
点击查看代码public class GuanCheng { public static void main(String[] args) { Buffer buffer = new Buffer(); Producer Jing = new Producer(buffer); Consumer Kai = new Consumer(buffer); new Thread(Jing).start(); new Thread(Kai).start(); } } class Chicken { private int id; public Chicken(int id){ this.id = id; } public int getId(){ return this.id; } } class Producer implements Runnable{ private Buffer buffer; public Producer(Buffer buffer){ this.buffer = buffer; } @Override public void run() { for (int i = 1; i <= 100; i++) { buffer.store(new Chicken(i)); } } } class Consumer implements Runnable{ private Buffer buffer; public Consumer(Buffer buffer){ this.buffer = buffer; } @Override public void run() { for (int i = 1; i <= 100; i++) { buffer.sell(); } } } class Buffer{ private final int MAX = 10; private Queue<Chicken> queue = new LinkedList<>(); public synchronized void store(Chicken chicken){ //若已有十只鸡,则停止生产并通知消费者消费;否则继续生产 if(queue.size() >= MAX){ try{ this.wait(); } catch (InterruptedException e){ System.out.println("仓库鸡满了!"); } } queue.offer(chicken); System.out.println("生产了第" + chicken.getId() + "只鸡" + ", 仓库余量为" + queue.size()); this.notify(); } public synchronized void sell() { //若没有鸡,则通知生产者进行生产;否则消费鸡 if(queue.size() == 0){ try{ this.wait(); } catch (InterruptedException e){ System.out.println("没有鸡可吃了!"); } } System.out.println("消费了第" + queue.poll().getId() +"只鸡"); this.notify(); } }
9 线程池
9.1 线程池概述
产生背景:线程经常创建和销毁、使用量特别大的资源(并发情况下的线程),对性能影响较大
思路:提前创建线程放入线程池中,使用时直接获取,使用完放回池中。(避免频繁创建销毁线程,实现线程重复利用)
优点:
- 提高响应速度(减少创建新线程时间)
- 降低资源消耗(重复利用线程池中线程,不需每次都创建)
- 便于线程管理 corePoolSize:核心池大小
- 最大线程数
- 线程没有任务时最多保持多长时间后终止
9.2 使用线程池
- JDK 5.0提供了线程池相关API:ExecutorSService和Executors
- ExecutorService:真正的线程池接口(ThreadPoolExecutor为其常见子实现类) void execute(Runnable command):执行任务/命令,无返回值,一般用来执行Runnable
- <T>Future<T> submit(Callable<T> task): 执行任务,有返回值。一般用来执行Callable
- void shutdown():关闭线程池 ...
9.3 使用示例
public class TestPool { public static void main(String[] args) { //1.创建服务,线程池 ExecutorService service = Executors.newFixedThreadPool(10); //2.执行 service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); //3.关闭连接 service.shutdown(); } }
相关文章推荐
- Java多线程-工具篇-BlockingQueue
- java 运行多线程轮询时,外部停止轮询
- java多线程的常见例子
- java 中如何避免多线程不安全
- java多线程与线程并发五:多个线程访问共享对象和数据的方式
- Java 多线程 并发编程
- java--创建多线程两种方法的比较
- 在多核或多处理器时代,为什么要特别 重视 Java 多线程 开发模式
- java 多线程 详解 生产者消费者 问题解决
- java多线程之一/Java内存模型(JMM)
- java高并发系列 - 第16天:JUC中等待多线程完成的工具类CountDownLatch,必备技能
- 40个Java多线程问题总结
- JAVA 多线程编程 --线程的调度策略
- 从jvm的角度来看java的多线程
- Java 多线程详解(五)------线程的声明周期
- java多线程
- Java 多线程编程之六:线程之间的通信(附源代码)
- Java多线程导论
- Java多线程导论
- 最全面的Java多线程用法解析