当前位置: 首页 > news >正文

Javase 基础加强 —— 11 线程池

本系列为笔者学习Javase的课堂笔记,视频资源为B站黑马程序员出品的《黑马程序员Java+AI智能辅助编程全套视频教程,java零基础入门到大牛一套通关》,章节分布参考视频教程,为同样学习Javase系列课程的同学们提供参考。

01 概述

用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能。

那么这时,线程池就是一个可以复用线程的技术。

在这里插入图片描述

02 创建线程池

JDK5.0起提供了代表线程池的接口:ExecutorService / ɪɡˈzekjʊtər /

如何创建线程池对象?

① 使用ExecutorService实现类ThreadPoolExecutor自创建一个线程池对象。

在这里插入图片描述

ExecutorService pool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

② 使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。

03 处理 Runnable 任务

ExecutorService的常用方法

在这里插入图片描述

MyRunnable.java

package ExecutorDemo;public class MyRunnable implements Runnable{@Overridepublic void run(){for(int i=0; i<5; i++){System.out.println(Thread.currentThread().getName());}}
}

ExecutorServiceDemo1.java

package ExecutorDemo;import java.util.concurrent.*;public class ExecutorServiceDemo1 {public static void main(String[] args) {//目标:创建线程池对象//1.使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象ExecutorService pool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());//2.使用线程池处理Runnable任务Runnable target = new MyRunnable();pool.execute(target); //提交第1个任务 创建第1个线程 自动启动线程处理这个任务pool.execute(target); //提交第1个任务 创建第1个线程 自动启动线程处理这个任务pool.execute(target); //提交第1个任务 创建第1个线程 自动启动线程处理这个任务pool.execute(target); //复用线程pool.execute(target); //复用线程//3.关闭线程池//pool.shutdown();}
}

问:什么时候开始创建临时线程?

新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时会创建临时线程。

问:什么时候会拒绝新任务?

新任务提交时发现核心线程和临时线程都在忙,任务队列也满了,此时会拒绝任务。

在这里插入图片描述

MyRunnable.java

package ExecutorDemo;public class MyRunnable implements Runnable{@Overridepublic void run(){for(int i=0; i<5; i++){System.out.println(Thread.currentThread().getName() + "输出" + i);try {Thread.sleep(Integer.MAX_VALUE);} catch (Exception e) {e.printStackTrace();}}}
}

ExecutorServiceDemo1.java

package ExecutorDemo;import java.util.concurrent.*;public class ExecutorServiceDemo1 {public static void main(String[] args) {//目标:创建线程池对象//1.使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象ExecutorService pool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());//2.使用线程池处理Runnable任务Runnable target = new MyRunnable();pool.execute(target); //召唤第1个正式工pool.execute(target); //召唤第2个正式工pool.execute(target); //召唤第3个正式工pool.execute(target); //门口等待1位pool.execute(target); //门口等待2位pool.execute(target); //门口等待3位pool.execute(target); //招聘第1个临时工pool.execute(target); //招聘第2个临时工pool.execute(target); //老板亲自服务//3.关闭线程池//pool.shutdown();}
}

在这里插入图片描述

04 处理 Callable 任务

ExecutorService的常用方法

在这里插入图片描述

MyCallable.java

package ExecutorDemo;import java.util.concurrent.Callable;public class MyCallable implements Callable<String> {private int n;public MyCallable(int n){this.n = n;}@Overridepublic String call() throws Exception{int sum = 0;for(int i=1; i<=n; i++){sum += i;}return Thread.currentThread().getName() + "子线程" + n + "计算sum为:" + sum;}
}

ExecutorServiceDemo2.java

package ExecutorDemo;import java.util.concurrent.*;public class ExecutorServiceDemo2 {public static void main(String[] args) {//目标:创建线程池对象//1.使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象ExecutorService pool = new ThreadPoolExecutor(3, 5, 10, TimeUnit.SECONDS,new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());//2.使用线程池处理Callable任务Future<String> f1 = pool.submit(new MyCallable(100));Future<String> f2 = pool.submit(new MyCallable(200));Future<String> f3 = pool.submit(new MyCallable(300));Future<String> f4 = pool.submit(new MyCallable(400));try {System.out.println(f1.get());System.out.println(f2.get());System.out.println(f3.get());System.out.println(f4.get());} catch (Exception e) {e.printStackTrace();}}
}

05 通过 Executors 创建新线程

Executors 是一个线程池的工具类,其提供了很多静态方法用于返回不同特点的线程池对象。

在这里插入图片描述

ExecutorService pool Executors.newFixedThreadPool(3);

在这里插入图片描述

06 并发/并行

当前正在运行的程序为一个独立的进程,而线程是属于进程的,一个进程中可以同时运行很多个线程。

进程中的线程是由CPU负责调度执行的,但CPU能同时处理线程的数量有限,为了保证全部线程都能往前执行,CPU会轮询为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发。

并发是虚假的同时,并行是真正的同时。

07 案例:红包雨游戏

需求:某企业有100名员工,员工的工号依次是1,2,3,4,…,100。现在公司举办了年会活动,活动中有一个红包雨环节,要求共计发出200个红包雨。其中小红包在1-30元之间,总占比为80%,大红包[31-100】元,总占比为20%。

分析:100个员工实际上就是100个线程,来竞争200个红包。

Test.java

package threadDemo;import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class Test {public static void main(String[] args) {List<Integer> redPacket = getRedPacket();//2.定义线程类,创建100个线程,竞争200个红包for(int i=1; i<=100; i++){new PeopleGetRedPacket(redPacket, i + "号程序员");}}public static List<Integer> getRedPacket(){Random r = new Random();//1.创建List集合,准备200个随机红包List<Integer> redPacket = new ArrayList<>();for(int i=1; i<=160; i++){redPacket.add(r.nextInt(30) + 1);}for(int i=1; i<=40; i++){redPacket.add(r.nextInt(70) + 31);}return redPacket;}
}

PeopleGetRedPacket.java

package threadDemo;import java.util.List;public class PeopleGetRedPacket extends Thread{//构造函数立大功!!!private List<Integer> redPacket;public PeopleGetRedPacket(List<Integer> redPacket, String name){super(name);this.redPacket = redPacket;}@Overridepublic void run(){//3.创建加锁机制,模拟抢红包过程String name = Thread.currentThread().getName();while(true){if(redPacket.size() == 0){break;}int index = (int)(Math.random() * redPacket.size());Integer money = redPacket.remove(index);System.out.println(name + "抢到了" + money + "元");if(redPacket.size() == 0){System.out.println("活动结束!");break;}try{Thread.sleep(10);}catch (Exception e){e.printStackTrace();}}}
}
http://www.dtcms.com/a/393737.html

相关文章:

  • 分布式锁-Redis实现
  • 对于ModelScope的AI模型git部署感悟
  • [论文阅读] 人工智能 + 软件工程 | 从“人工扒日志”到“AI自动诊断”:LogCoT框架的3大核心创新
  • 【软考中级 - 软件设计师 - 应用技术】软件工程案例分析之软件测试实践
  • AI:读《老人与海》有感
  • 定制开发开源AI智能名片S2B2C商城小程序:产业互联网时代的创新商业模式
  • .env与.gitignore:现代软件开发中的环境管理与版本控制防护
  • 理解重参数化
  • css 给文本添加任务图片背景
  • CSS中的选择器、引入方式和样式属性
  • CSS 入门与常用属性详解
  • Linux 下 PostgreSQL 安装与常用操作指南
  • 【Linux】CentOS7网络服务配置
  • 使用C++编写的一款射击五彩敌人的游戏
  • 【LeetCode hot100|Week3】数组,矩阵
  • linux-环境配置-指令-记录
  • 自学嵌入式第四十四天:汇编
  • RTX 4090助力深度学习:从PyTorch到生产环境的完整实践指南——模型部署与性能优化
  • PythonOCC 在二维平面上实现圆角(Fillet)
  • Unity 性能优化 之 实战场景简化(LOD策略 | 遮挡剔除 | 光影剔除 | 渲染流程的精简与优化 | Terrain地形优化 | 主光源级联阴影优化)
  • [GXYCTF2019]禁止套娃1
  • 【论文阅读】-《Triangle Attack: A Query-efficient Decision-based Adversarial Attack》
  • 云微短剧小程序系统开发:赋能短剧生态,打造全链路数字化解决方案
  • 《从延迟300ms到80ms:GitHub Copilot X+Snyk重构手游跨服社交系统实录》
  • 力扣2132. 用邮票贴满网格图
  • Halcon学习--视觉深度学习
  • LeetCode:40.二叉树的直径
  • dplyr 是 R 语言中一个革命性的数据操作包,它的名字是 “data plier“ 的缩写,意为“数据折叠器“或“数据操作器“
  • 使用Node.js和PostgreSQL构建数据库应用
  • 设计模式(C++)详解—享元模式(1)