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

设计模式(单例模式,工厂模式),线程池

目录

什么是设计模式?

单例模式

饿汉模式

懒汉模式

工厂模式

线程池

线程池种类

ThreadPoolExcutor的构造方法:

手动实现一个线程池 


什么是设计模式?

计算机行业程序员水平层次不齐,为了让所有人都能够写出规范的代码,于是就有了设计模式,针对一些典型的场景,给出一些典型的解决方案

单例模式

单例模式 ==> 单个实例(对象)

在一些场景中,有的特定类只能创建一个实例,不能创建多个实例
使用了单例模式后,此时就不能创建多个实例了,我们想创建多个实例都难,单例模式就是针对上述的需求场景进行了更强制的保证,通过巧用java的语法,达成某个类 只能被创建出一个实例这样的效果(当程序员不小心创建了多个实例,就会报错)

单例模式实现

饿汉模式

// 饿汉模式的 单例模式 实现
// 此处保证 Singleton 这个类只能创建出一个实例
class Singleton{// 在此处,先把实例给创建出来private static Singleton instance = new Singleton();// 如果需要使用 instance,通过统一的Singleton.getInstance() 方式获取public static Singleton getInstance(){return instance;}// 为了避免 Singleton 类不小心被复制多份// 把构造方法设为 private,在类外面,就无法通过new 的方式来创建这个 Singleton了private Singleton(){};
}
public class Thread3 {public static void main(String[] args) {Singleton s = Singleton.getInstance();Singleton s2 = Singleton.getInstance();System.out.println(s==s2);Singleton s3 = new Singleton(); // 报错,原因是Singleton的构造方法被private修饰,因此无法通过new的方式创建Singleton对象}
}

懒汉模式

class Singleton2{ private static volatile Singleton2 instance = null; //使用volatile表示instance是个易变的public static Singleton2 getInstance(){if (instance==null) {   // 此处负责判断是否要加锁synchronized (Singleton2.class) {if(instance==null){   // 此处判断是否要创建对象instance = new Singleton2();}}}return instance;}private Singleton2(){};
}

懒汉模式下,有创建Singleton对象的操作(写操作),所以可能会出现线程安全问题,因此我们要进行加锁操作,并标注instance是一个易变的对象(避免内存可见性问题,和指令重排序问题)

工厂模式

工厂模式: 使用普通的方法,来代替构造方法,创建对象.  在java中,构造方法存在一定缺陷,构造方法要求构造名必须为类名(方法名相同),构造参数可以不同,没用返回值.如果我们只构造一种对象可以忽略这个缺陷,如果构造多种不同的情况的对象可能会出现问题,比如想要实现俩个不同的构造方法,但是它们的参数类型恰好都相同,但表达的意义不同,这时java就无法区分了.为了解决这个问题,就可以使用工程模式

比如分别使用笛卡尔坐标系和极坐标系表示坐标

import java.awt.*;
class PointFactory{public static Point makePointByXY(double x,double y){}public static Point makePointByRA(double r,double a){}
}
public class Thread6 {public static void main(String[] args) {Point p = PointFactory.makePointByXY(10,20);Point p2 = PointFactory.makePointByRA(10,30);}
}

线程池

线程存在的意义: 使用进程实现并发编程,"太重了",引入线程(轻量级进程),创建线程比创建线程更高效,销毁线程比销毁进程更高效,调度线程比调度进程更高效,此时使用多线程就可以在很多时候代替进程实现并发编程了

线程池存在的意义: 当我们需要频繁创建销毁线程的时候,就发现开销也很大,想要进一步的提高效率,可以: 1.搞一个协程(轻量级线程) 2.使用线程池,事先把需要使用的线程创建好,放到池中,后面需要使用的时候,从池中获取,如果用完了,再还给池.(创建线程和销毁线程是交由操作系统内核去完成的,从池子里获取/还给池,是自己用户代码就能实现的,不必交给内核操作)

public class Thread5 {public static void main(String[] args) {// 此处就构造了一个 10 个线程的线程池,就可以随时安排这些线程干活了ExecutorService pool =  Executors.newFixedThreadPool(10);// 当前往线程池中放了1000个任务,这1000个任务由线程池中的10个线程去执行for (int i = 0;i < 1000;i++) {pool.submit(()->{System.out.println("hello");});}}
}

线程池提供了一个重要的方法,submit,可以给线程池提交若干个任务,这若干个任务可以由线程池中的线程去执行完成..线程池中创建的线程是前台线程,需要执行完成后,主线程才可以结束. 
这里1000个任务相当于在一个队列中,线程池中的这10个线程就依次取这个队列中的任务,取一个就执行一个,执行完成后,再在这个队列中取任务去执行 

线程池种类

这些线程池,本质上都是通过包装 ThreadPoolExecutor 来实现的 

ThreadPoolExcutor的构造方法:

corePoolSize : 核心线程数,

maximumPoolSize:  最大线程数,相当于线程池把线程分为俩大类,一类是核心线程,一类是非核心线程,最大线程数就是核心线程和非核心线程之和
一个程序有时任务多,有时任务少,如果任务多,我们就需要多一些线程,如果任务少,就需要线程尽量少,此时我们就可以保留核心线程,而淘汰掉一些非核心线程

实际开发中,线程池的线程数设定成多少合适?

程序分为CPU密集型,每个线程执行的任务都需要狂转CPU(进行一系列算术运算),此时线程池线程数最多不超过CPU核数,因为cpu密集型要一直占用cpu,创建更多的线程也没用
IO密集型,每个线程的工作就是等待IO(读写硬盘,读写网卡,等待用户输入),不占CPU,此时这样的线程处于阻塞状态,不参与CPU调度,这个时候创建多个线程,不再受制于CPU核数了
实践中确定线程数,通过实验的方式,康康设置几个线程合适

long keepAliveTime: 非核心线程数不工作的最大时间,如果超过这个时间就销毁

TimeUnit unit: 时间单位,ms,s,分钟,小时......

BlockingQueue<Runnable> workQueue: 线程池的任务队列

ThreadFactory threadFactory: 用于创建线程

RejectedExecutionHandler handler: 描述了线程池的"拒绝策略",是一个特殊的对象,描述了当线程池任务队列满了之后,如果继续添加任务,线程池会有什么样的行为,总共有以下4种策略
ThreadPoolExcutor.AbortPolicy: 如果任务队列满了,再新增任务,直接抛出异常
ThreadPoolExcutor.CallerRunsPoliy: 如果任务队列满了,多出来的任务,谁加的就由谁去执行(交给调用者去执行)
ThreadPoolExcutor.DisardOlderdestPolicy: 如果任务队列满了,就丢弃最老的任务
ThreadPoolExcutor.DiscardPolicy: 如果任务队列满了,就丢弃最新的任务

手动实现一个线程池 

一个线程池中至少有俩个部分,一个是阻塞队列,用来保存任务,一个是若干个工作线程

class MyThreadPool{private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();// n 表示线程数量public MyThreadPool(int n){// 创建 n 个线程for (int i = 0; i < n; i++) {Thread t = new Thread(()->{while (true){try {Runnable runnable =  queue.take();runnable.run();} catch (InterruptedException e) {e.printStackTrace();}}});t.start();}}// 注册任务交给线程池public void submit(Runnable runnable) {try {queue.put(runnable);} catch (InterruptedException e) {e.printStackTrace();}}
}

相关文章:

设计模式(单例模式,工厂模式),线程池

目录 什么是设计模式? 单例模式 饿汉模式 懒汉模式 工厂模式 线程池 线程池种类 ThreadPoolExcutor的构造方法: 手动实现一个线程池 什么是设计模式? 计算机行业程序员水平层次不齐,为了让所有人都能够写出规范的代码,于是就有了设计模式,针对一些典型的场景,给出一…...

在mybatis中的mapper.xml中如何使用parameterType实现方法单个传参,对象传参,多参数传参.

在MyBatis的mapper.xml文件中&#xff0c;可以使用parameterType属性来指定方法的参数类型。parameterType属性用于指定传递给映射方法的参数类型&#xff0c;这将影响到MyBatis在映射方法执行时如何处理参数。 以下是三种不同情况下如何在mapper.xml中使用parameterType实现方…...

No120.精选前端面试题,享受每天的挑战和学习

文章目录 浏览器强制缓存和协商缓存cookie&#xff0c;localStorage、sessionStoragejs闭包&#xff0c;原型&#xff0c;原型链箭头函数和普通函数的区别promise的状态扭转 浏览器强制缓存和协商缓存 浏览器缓存是浏览器用于提高网页加载速度的一种机制。浏览器缓存分为强制缓…...

c# 访问sqlServer数据库时的连接字符串

//sql server 身份验证的场合&#xff0c; 连接字符串 private string ConnstrSqlServer "server服务器名称;uid登录名称;pwd登录密码;database数据库名称"; //windows 身份验证连接字符串 private string ConnstrWindows "server服务器名称;database数据库…...

排序算法概述

1.排序算法分类 **比较类算法排序&#xff1a;**通过比较来决定元素的时间复杂度的相对次序&#xff0c;由于其时间复杂度不能突破 O ( n l o g n ) O(nlogn) O(nlogn)&#xff0c;因此也称为非线性时间比较类算法 **非比较类算法排序&#xff1a;**不通过比较来决定元素间的…...

ChatGPT在高等教育中的应用利弊探讨

​人工智能在教育领域的应用日益广泛。2022年11月OpenAI开发的聊天机器人ChatGPT在全球范围内流传开来&#xff0c;其中用户数量最多的国家是美国(15.22%)。由于ChatGPT应用广泛&#xff0c;具有类似人类回答问题的能力&#xff0c;它正在成为许多学生和教育工作者的可信赖伙伴…...

Java之API详解之Runtime的详细解析

3.1 概述 Runtime表示Java中运行时对象&#xff0c;可以获取到程序运行时设计到的一些信息 3.2 常见方法 常见方法介绍 我们要学习的Object类中的常见方法如下所示&#xff1a; public static Runtime getRuntime() //当前系统的运行环境对象 public void exit(int statu…...

机器学习之softmax

Softmax是一个常用于多类别分类问题的激活函数和归一化方法。它将一个向量的原始分数&#xff08;也称为 logits&#xff09;转换为概率分布&#xff0c;使得每个类别的概率值在0到1之间&#xff0c;同时确保所有类别的概率之和等于1。Softmax函数的定义如下&#xff1a; 对于…...

npm script命令

1 串行/并行执行命令 //串行 npm-run-all text test npm run text && npm run test //并行改成& npm-run-all --parallel text test npm run text & npm run test2 传递参数 {"lint": "eslint js/*.js","lint:fix"&#xff1a…...

【力扣周赛】第360场周赛

【力扣周赛】第360场周赛 8015.距离原点最远的点题目描述解题思路 8022. 找出美丽数组的最小和题目描述解题思路 8015.距离原点最远的点 题目描述 描述&#xff1a;给你一个长度为 n 的字符串 moves &#xff0c;该字符串仅由字符 ‘L’、‘R’ 和 ‘_’ 组成。字符串表示你在…...

php环境变量的配置步骤

要配置PHP的环境变量&#xff0c;以便在命令行中直接使用php命令&#xff0c;以下是一般的步骤&#xff1a; Windows 操作系统 下载和安装PHP&#xff1a;首先&#xff0c;你需要从PHP官方网站&#xff08;https://www.php.net/downloads.php&#xff09;下载适用于你的操作系…...

Kdtree

Kdtree kdtree 就是在 n 维空间对数据点进行二分&#xff1b;具体先确定一个根&#xff0c;然后小于在这个维度上的根的节点在左边&#xff0c;大于的在右边&#xff0c;再进行下一个维度的划分。直到维度结束&#xff0c;再重复&#xff0c;或者直到达到了结束条件&#xff1…...

算法leetcode|74. 搜索二维矩阵(rust重拳出击)

文章目录 74. 搜索二维矩阵&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a; 分析&#xff1a;题解&#xff1a;rust&#xff1a;go&#xff1a;c&#xff1a;python&#xff1a;java&#xff1a; 74. 搜索二维矩阵&#xff1a; 给你一个满足下述两条属性的…...

element浅尝辄止7:InfiniteScroll 无限滚动

滚动加载&#xff1a;滚动至底部时&#xff0c;加载更多数据。 1.如何使用&#xff1f; //在要实现滚动加载的列表上上添加v-infinite-scroll&#xff0c;并赋值相应的加载方法&#xff0c; //可实现滚动到底部时自动执行加载方法。<template><ul class"infinit…...

Day05-Vue基础

Day05-Vue基础 一、单向数据流 父子组件通信。会在父组件中定义好数据,将数据传递给子组件,可以使用这个数据 Vue中针对props这个属性提出了一个单向数据流的概念。 Vue针对props做了一些限制,可以接受值,使用这个值,规范中不要去直接修改这个值 目的是为了对数据流进…...

《机器学习在车险定价中的应用》实验报告

目录 一、实验题目 机器学习在车险定价中的应用 二、实验设置 1. 操作系统&#xff1a; 2. IDE&#xff1a; 3. python&#xff1a; 4. 库&#xff1a; 三、实验内容 实验前的猜想&#xff1a; 四、实验结果 1. 数据预处理及数据划分 独热编码处理结果&#xff08;以…...

14. Docker中实现CI和CD

目录 1、前言 2、什么是CI/CD 3、部署Jenkins 3.1、下载Jenkins 3.2、启动Jenkins 3.3、访问Jenkins页面 4、Jenkins部署一个应用 5、Jenkins实现Docker应用的持续集成和部署 5.1、创建Dockerfile 5.2、集成Jenkins和Docker 6、小结 1、前言 持续集成(CI/CD)是一种…...

【多思路解决喝汽水问题】1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水

题目内容 喝汽水问题 喝汽水&#xff0c;1瓶汽水1元&#xff0c;2个空瓶可以换一瓶汽水&#xff0c;给20元&#xff0c;可以喝多少汽水&#xff08;编程实现&#xff09;。 题目分析 数学思路分析 根据给出的问题和引用内容&#xff0c;我们可以得出答案。 首先&#xff…...

P1591 阶乘数码(Java高精度)

题目描述 求 n ! n! n! 中某个数码出现的次数。 输入格式 第一行为 t ( t ≤ 10 ) t(t \leq 10) t(t≤10)&#xff0c;表示数据组数。接下来 t t t 行&#xff0c;每行一个正整数 n ( n ≤ 1000 ) n(n \leq 1000) n(n≤1000) 和数码 a a a。 输出格式 对于每组数据&a…...

Mybatis的动态SQL及关键属性和标识的区别(对SQL更灵活的使用)

&#xff08; 虽然文章中有大多文本内容&#xff0c;想了解更深需要耐心看完&#xff0c;必定大有受益 &#xff09; 目录 一、动态SQL ( 1 ) 是什么 ( 2 ) 作用 ( 3 ) 优点 ( 4 ) 特殊标签 ( 5 ) 演示 二、#和$的区别 2.1 #使用 ( 1 ) #占位符语法 ( 2 ) #优点 2.…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

加密通信 + 行为分析:运营商行业安全防御体系重构

在数字经济蓬勃发展的时代&#xff0c;运营商作为信息通信网络的核心枢纽&#xff0c;承载着海量用户数据与关键业务传输&#xff0c;其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级&#xff0c;传统安全防护体系逐渐暴露出局限性&a…...