宁波网站建设鲤斯设计动漫设计和动漫制作技术哪个更好
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:15
当前位置: 首页 > news >正文
宁波网站建设鲤斯设计,动漫设计和动漫制作技术哪个更好,微商分销平台有哪些,wordpress哪款主题好用作者#xff1a;困了电视剧 专栏#xff1a;《JavaEE初阶》 文章分布#xff1a;这是关于java多线程案例的文章#xff0c;进行了对单例模式、阻塞队列及生产者消费者模型、定时器和线程池的讲解#xff0c;希望对你有所帮助#xff01; 目录 单例模式 懒汉模式实现 饿… 作者困了电视剧 专栏《JavaEE初阶》 文章分布这是关于java多线程案例的文章进行了对单例模式、阻塞队列及生产者消费者模型、定时器和线程池的讲解希望对你有所帮助 目录 单例模式 懒汉模式实现 饿汉模式实现 阻塞式队列 标准库中的阻塞式队列 生产者消费者模型 降低耦合 削峰填谷 低配版阻塞式队列的简单自我实现 定时器 标准库中的定时器 低配版定时器的简单自我实现 线程池 标准库中的线程池 代码实现 创建线程池的参数的意义 线程池的拒绝策略 低配版线程池的简单自我实现 单例模式 单例模式是一个非常常见的设计模式。 什么是设计模式? 设计模式好比象棋中的 棋谱. 红方当头炮, 黑方马来跳. 针对红方的一些走法, 黑方应招的时候有 一些固定的套路. 按照套路来走局势就不会吃亏. 软件开发中也有很多常见的 问题场景. 针对这些问题场景, 大佬们总结出了一些固定的套路. 按照 这个套路来实现代码, 也不会吃亏. 单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例。我们在日常的编程中一定有类似这样的需求比如我们现在有一个wife类这个wife类只能实例化一个“wife”否则就会发生逻辑上的错误这时我们就需要这个单例模式来约束我们只能创建一个wife对象。单例模式主要分为“饿汉”和“懒汉”两种具体实现方式。 懒汉模式实现 以洗碗举例懒汉模式就是我中午吃完饭我留着碗不急着洗等我到晚上需要再次吃饭的时候我再去洗而且我只洗我吃晚饭需要的碗不需要的碗我仍然不洗直到我需要为止。 抛开现实的卫生因素这样做的效率会比我吃完就全洗的效率更高占用的资源更少具体到代码中就是只有当我需要他的实例时我在创建不需要就不创建。 class Singleton{//饿汉模式不调用就不创建实例//用static进行修饰使其成为一个类变量这样这个类中就只有一个private static Singleton instance null;public static Singleton getSingleton(){//当这个不为空的时候此时就是单纯的读操作不需要再像第一次执行一样考虑线程安全问题if (instance null){synchronized (Singleton.class){//判断是否为空为空就进行实例化if (instance null){instance new Singleton();}}}return instance;}//解决了用方法进行调用的且只有一个需求现在还需要封印用new来进行实例化的步骤用private修饰构造方法即可private Singleton(){} } 加锁是因为在多线程环境下可能会导致不同线程new出来的对象不同所以要加锁。 同时这里的两个判断instance为空的条件虽然写了两次但不可省略原因如下 1.最重要的一点是初心不同第一个判断是为了判断是否需要在进行写操作如果只需要 进行读操作的话则不需要加锁以提高线程的执行效率。加锁是一个非常低效的操作所 以非必要不加锁。第二个判断则是判断是否为空为空则需要进行实例化这里两者一 样只是一种巧合。 2.虽然这两个判断条件只隔有一个锁但是在锁竞争的影响下他们之间被执行的间隔可能会 是很长时间在这段时间里无法保证instance没有被删掉。 饿汉模式实现 饿汉模式就是我很“饿”所以我很“勤快”当我中午饭吃完后我立即就把碗什么的全给洗了在代码中的实现也是我一开始就将其进行赋值用不用什么时候用不关心。 class Singleton{private static Singleton instance new Singleton();public static Singleton getSingleton(){return instance;}private Singleton(){} } 阻塞式队列 阻塞队列是一种特殊的队列. 也遵守 先进先出 的原则。 阻塞队列能是一种线程安全的数据结构, 并且具有以下特性: 1.当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素. 2.当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中插入元素. 阻塞队列的一个典型应用场景就是 生产者消费者模型. 这是一种非常典型的开发模型。 标准库中的阻塞式队列 put方法是向队列中加入元素而take方法则是从队列中拿出元素。 生产者消费者模型 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。 生产者和消费者彼此之间不直接通讯而通过阻塞队列来进行通讯所以生产者生产完数据之后不用等 待消费者处理直接扔给阻塞队列消费者不找生产者要数据而是直接从阻塞队列里取 降低耦合 举个栗子比如现在有AB两个服务器A是生产者B是消费者现在我们不采用这种生产者消费者模型那A和B就相当于直接进行交互假如A向B发送一个请求B给A一个回应如果此时A崩了那B也就没什么用了即也就跟着崩了这就是强耦合。 而如果此时我们在中间加一个阻塞队列服务器即采用生产者消费者模型。 这样A和B两个服务器只认识这个阻塞队列服务器并不认识对方此时如果A崩了那B并不会受到太大的影响。这就大大降低了两个服务器之间的耦合程度提高了稳定性。 削峰填谷 这个模型还有一个巨大的作用就是削峰填谷。 现在依旧是AB两个服务器假设A服务器是一个与网购相关的服务器在某一时刻有一个促销活动这个活动的出现使A服务器发送的请求在短时间内大大增加这是就对需要对其进行回应的B服务器造成了极大的负担很可能会导致服务器的的崩溃! 这时如果我们使用生产着消费者模型那爆炸式增长的请求就会直接进入到阻塞队列服务器而B服务器就会按照“自己”的速度一一进行回应“峰”是这样“谷”也是如此。 注由于阻塞队列服务器的业务较少所以相比于业务很多的A和B服务器要稳定很多。 低配版阻塞式队列的简单自我实现 public class MyBlockingQueue {//循环队列但是加上了等待阻塞private int[] items new int[1000];volatile private int size 0;volatile private int head 0;volatile private int tail 0;synchronized public void put(int elem) throws InterruptedException {if (size items.length){this.wait();}items[tail] elem;tail;size;if (tail items.length){tail 0;}//此时阻塞队列已经put出了一个元素也就是说现在一定不满此时进行阻塞等待的就可以被唤醒了this.notify();}synchronized public int take() throws InterruptedException {if (size 0){this.wait();}int ret items[head];head;size–;if (head items.length){head 0;}this.notify();return ret;} } 简易版的实现希望对你有所启发。 定时器 标准库中提供了一个 Timer 类.。 Timer 类的核心方法为 schedule . schedule 包含两个参数. 第一个参数指定即将要执行的任务代码, 第二个参数指定多长时间之后 执行 (单位为毫秒). 标准库中的定时器 TimerTask是一个实现了Runnable接口的抽象类但由于不是函数式接口所以不能使用Lambda表达式进行书写。 三秒后在控制台中打出了Hello。 低配版定时器的简单自我实现 class MyTask implements ComparableMyTask {public Runnable runnable;public long time;public MyTask(Runnable runnable,long delay){this.runnable runnable;//这里的time是时间戳所以需要先找到目前的时间戳然后加上需要延时的时间this.time System.currentTimeMillis() delay;}//因为要放入带有优先级的阻塞队列中所以我们要指定一个比较规则实现comparable接口Overridepublic int compareTo(MyTask o) {return (int)(this.time - o.time);} }public class MyTimer {//这个结构带有优先级的阻塞队列核心数据结构private PriorityBlockingQueueMyTask queue new PriorityBlockingQueue();private Object locker new Object();//这个“时间表”方法就是将我们的任务放到队列中public void shedule(Runnable runnable,long delay){MyTask myTask new MyTask(runnable,delay);queue.put(myTask);locker.notify();}//这个构造方法是执行我放到“时间表”中的任务当我实例化开始就开始计时public MyTimer(){Thread t new Thread(() - {while (true){try {synchronized (locker){MyTask myTask queue.take();long curTime System.currentTimeMillis();if (myTask.time curTime){myTask.runnable.run();}else{queue.put(myTask);locker.wait(myTask.time - curTime);}}} catch (InterruptedException e) {e.printStackTrace();}}});t.start();} } 相关代码已用注释标记出了意思如有不清楚的地方还请评论区讨论~~ 线程池 在CPU内部每次需要使用一个线程都需要重新创建并且销毁这每次的创建销毁都需要消耗资源那能不能这样做我一次创建一定数量的线程并把它们放到一个名字叫“线程池”的容器中这样每当我们在需要用线程的时候就不需要再重新创建了并且当这个线程的run方法执行完毕后就不需要在销毁这个线程而是直接将这个线程再放进线程池当中以便下次使用这样就又节省了销毁线程的资源。 举个栗子 我现在开了一个小卖部我每次需要去送外卖不用线程池就是每次需要送外卖的时候都重新雇一个人然后他送完外卖后我立刻将他解雇。 而线程池就是你一次雇几个人然后这几个人去送外卖他们送完后也不解雇等着下次外卖到来。这样就节约了很多的资源。 标准库中的线程池 代码实现 import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class ThreadDemo3 {public static void main(String[] args) {//通过Executors中的静态方法来进行线程池的创建现在这个线程池中有十个线程ExecutorService pool Executors.newFixedThreadPool(10);//我们可以通过submit方法来注册一个任务到线程池当中for ( int i0;i1000;i ){int num i;pool.submit(new Runnable() {Overridepublic void run() {System.out.println(hello num);}});}} } 这里我们不能通过直接new来创建对象必须要通过调用静态方法才行这时一个叫做工厂模式的设计模式在我们日常的一些需求中仅仅使用构造方法的重载无法满足有时候就需要工厂模式来帮助我们举个栗子 创建一个point对象我需要描述他的坐标假设是二维平面我们可以通过x和y来进行描述这时我们构造方法传两个参数就行了但是用极坐标的ρ和角度也可以进行创建这时候我们就发现这两种构造方法传的参数类型和数量都是一样的无法区分开于是工厂模式应运而生。 Executors 创建线程池的几种方式 newFixedThreadPool: 创建固定线程数的线程池 newCachedThreadPool: 创建线程数目动态增长的线程池. newSingleThreadExecutor: 创建只包含单个线程的线程池. newScheduledThreadPool: 设定 延迟时间后执行命令或者定期执行命令. 是进阶版的 Timer. Executors 本质上是 ThreadPoolExecutor 类的封装. 这段代码的执行结果为 十个线程会将这些任务执行完随机没有顺序。 创建线程池的参数的意义 corePoolSize是核心线程数 maxmumPoolSize是最大线程数 当目前任务数量较多时线程池会多创建一些临时线程。 核心线程就相当于“正式员工”而这些临时线程就相当于“实习生”当任务变少时线程池就会考虑将这些“实习生”辞退即销毁这些临时线程但核心线程则不会受影响会一直保留。 long keepAliveTime是临时线程保持存活的时间 TimeUnit unit是时间的单位 当任务较少时这些临时线程并不会立即被销毁而是暂时存活一段时间因为线程池不确定过一会会不会又有大量的任务加进来所以会保留一段时间来节约资源。 workQueue是阻塞队列 threadFactory是工厂模式 线程池要管理很多个任务这些任务的底层就是通过阻塞队列来管理的程序员可以手动指定一个阻塞队列这样就可以清楚地知道队列中的信息submit方法就是将任务放到这个阻塞队列中。 工厂模式就是创建辅助线程的类 handler是线程池的拒绝策略。 线程池的拒绝策略 我们可以将任务添加到线程池当中来提高我们程序运行的效率但是线程池的承载能力毕竟是有限的当我们向其中添加的任务过多时线程池就会拒绝任务的添加标准库提供了四种拒绝策略。 1.如果满了还继续加任务那添加操作就会直接抛出异常新任务老任务都无法执行。 2.添加的线程自己负责执行这个任务即劳资不仅不干劳资还要怼回去。 3.丢弃最老的任务将新的任务添加。 4.丢去最新的任务即不理这个新任务该咋咋还咋咋。 低配版线程池的简单自我实现 import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque;public class MyThreadPool {//用阻塞队列来存放任务private BlockingQueueRunnable queue new LinkedBlockingDeque();public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}public MyThreadPool(int n){//创建n个线程for ( int i0;in;i ){Thread t new Thread(() -{//每个线程内部做的任务是只要队列中有任务我就抢着执行try {while (true){Runnable runnable queue.take();runnable.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();}} } 相关代码注释已给出。 以上就是本篇博客的全部内容如有疏漏还请指正
- 上一篇: 宁波网站建设公司信息查询潍坊网站建设建站
- 下一篇: 宁波网站建设联系方法企业做网站这些问题必须要注意
相关文章
-
宁波网站建设公司信息查询潍坊网站建设建站
宁波网站建设公司信息查询潍坊网站建设建站
- 技术栈
- 2026年03月21日
-
宁波网站建设公司名单推荐衡阳网站seo
宁波网站建设公司名单推荐衡阳网站seo
- 技术栈
- 2026年03月21日
-
宁波网站建设的过程通辽网站开发
宁波网站建设的过程通辽网站开发
- 技术栈
- 2026年03月21日
-
宁波网站建设联系方法企业做网站这些问题必须要注意
宁波网站建设联系方法企业做网站这些问题必须要注意
- 技术栈
- 2026年03月21日
-
宁波网站建设哪家好做网站需要每年都交钱吗
宁波网站建设哪家好做网站需要每年都交钱吗
- 技术栈
- 2026年03月21日
-
宁波网站建设设计图jsp做的网站带数据库
宁波网站建设设计图jsp做的网站带数据库
- 技术栈
- 2026年03月21日
