剧前爆米花--爪哇岛寻宝】java多线程案例——单例模式、阻塞队列及生产者消费者模型、定时器、线程池
作者:困了电视剧
专栏:《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方法则是从队列中拿出元素。
生产者消费者模型
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等 待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取
降低耦合
举个栗子:比如现在有A,B两个服务器,A是生产者,B是消费者,现在我们不采用这种生产者消费者模型,那A和B就相当于直接进行交互,假如A向B发送一个请求,B给A一个回应,如果此时A崩了,那B也就没什么用了,即也就跟着崩了,这就是强耦合。
而如果此时我们在中间加一个阻塞队列服务器,即采用生产者消费者模型。
这样A和B两个服务器只认识这个阻塞队列服务器,并不认识对方,此时,如果A崩了,那B并不会受到太大的影响。这就大大降低了两个服务器之间的耦合程度,提高了稳定性。
削峰填谷
这个模型还有一个巨大的作用就是削峰填谷。
现在依旧是A,B两个服务器,假设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 Comparable<MyTask> {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 PriorityBlockingQueue<MyTask> 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 i=0;i<1000;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 BlockingQueue<Runnable> queue = new LinkedBlockingDeque<>();public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}public MyThreadPool(int n){//创建n个线程for ( int i=0;i<n;i++ ){Thread t = new Thread(() ->{//每个线程内部做的任务是,只要队列中有任务我就抢着执行try {while (true){Runnable runnable = queue.take();runnable.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();}}
}
相关代码注释已给出。
以上就是本篇博客的全部内容,如有疏漏还请指正!
相关文章:
剧前爆米花--爪哇岛寻宝】java多线程案例——单例模式、阻塞队列及生产者消费者模型、定时器、线程池
作者:困了电视剧 专栏:《JavaEE初阶》 文章分布:这是关于java多线程案例的文章,进行了对单例模式、阻塞队列及生产者消费者模型、定时器和线程池的讲解,希望对你有所帮助! 目录 单例模式 懒汉模式实现 饿…...
Guitar Pro8中文版更新说明及系统要求介绍
Guitar Pro吉他软件是初学作曲,特别是同时又初学吉他的朋友们的良师益友,是一款极佳的初级软件,是非实时作曲软件之中的一件佳作。Guitar Pro在吉他和弦、把位的显示、推算、查询、调用等方面,也异常方便、简洁、直观和浩瀚&#…...
【id:19】【20分】A. 三数论大小(引用)
题目描述 输入三个整数,然后按照从大到小的顺序输出数值。 要求:定义一个函数,无返回值,函数参数是三个整数参数的引用,例如int &a, int &b, int &c。在函数内对三个参数进行排序。主函数调用这个函数进行…...
To_Heart—总结——FWT(快速沃尔什变换)
目录闲话拿来求什么或与异或闲话 这个比FFT简单了很多呢,,大概是我可以学懂的水平! 好像是叫 快速沃尔什变换 ? 拿来求什么 以 FFT 来类比。我们 FFT 可以在 O(nlogn)\mathrm{O(nlogn)}O(nlogn) 的复杂度下实现求解࿱…...
Google巨大漏洞让Win10、11翻车,小姐姐马赛克白打了
早年间电脑截图这项技能未被大多数人掌握时,许多人应该都使用过手机拍屏幕这个原始的方式。 但由于较低的画面质量极其影响其他用户的观感,常常受到大家的调侃。 但到了 Win10、11 ,预装的截图工具让门槛大幅降低。 WinShiftS 就能快速打开…...
腾讯云服务器部署内网穿透(让其他人在不同ip可以访问我们localhost端口的主机项目)(nps开源项目)
首先打开shell连接我们的云服务器 然后我们再opt目录下面创建一个文件夹用来存放我们的压缩包和文件 mkdir /opt/nps 这个是它官方的安装图解.所以我们按照这个docker安装过程来: 然后我们用docker安装镜像.这样的话比较简单一点 docker pull ffdfgdfg/nps 然后我们查看docker…...
IDS、恶意软件、免杀技术、反病毒技术、APT、对称加密、非对称加密以及SSL的工作过程的技术介绍
IDS的简单介绍IDS是:入侵检测系统(intrusion detection system,简称“IDS”)是一种对网络传输进行即时监视,在发现可疑传输时发出警报或者采取主动反应措施的网络安全设备。它与其他网络安全设备的不同之处便在于&…...
怎么把pdf转换成高清图片
怎么把pdf转换成高清图片?可以使用以下两种方法: 方法一:使用Adobe Acrobat Pro DC 1、打开需要转换的PDF文件,点击“文件”菜单中的“导出为”,在弹出的菜单中选择“图像”,然后选择“JPEG”。 2、在“…...
MATLAB 系统辨识 + PID 自动调参
系统辨识 PID 自动调参 文章目录系统辨识 PID 自动调参1. 导入数据1.1 从 Excel 中导入数据2. 系统辨识3. PID 自动调参1. 导入数据 1.1 从 Excel 中导入数据 如果不是从Excel中导入可以跳过该步骤 导入函数: [num,txt,raw]xlsread(xxx\xxx.xlsx);num返回的是…...
【vue3】组合式API之setup()介绍与reactive()函数的使用·上
>😉博主:初映CY的前说(前端领域) ,📒本文核心:setup()概念、 reactive()的使用 【前言】vue3作为vue2的升级版,有着很多的新特性,其中就包括了组合式API,也就是是 Composition API。学习组合…...
爬虫Day3 csv和bs4
爬虫Day3 csv和bs4 一、CSV的读和写 1. 什么是csv文件 csv文件叫做:逗号分隔值文件,像Excel文件一样以行列的形式保存数据,保存数据的时候同一行的多列数据用逗号隔开。 2. csv文件的读写操作 1) csv文件读操作 from csv import reader…...
nnAudio的简单介绍
官方实现 https://github.com/KinWaiCheuk/nnAudio; 论文实现: nnAudio: An on-the-Fly GPU Audio to Spectrogram Conversion Toolbox Using 1D Convolutional Neural Networks; 以下先对文章解读: abstract 在本文中&#x…...
【id:134】【20分】B. 求最大值最小值(引用)
题目描述 编写函数void find(int *num,int n,int &minIndex,int &maxIndex),求数组num(元素为num[0],num[1],...,num[n-1])中取最小值、最大值的元素下标minIndex,maxIndex(若有相同最值࿰…...
Java 面向对象
一、Java 8 增强的包装类 Java是面向对象的编程语言,但它也包含了8种基本数据类型,这8种基本数据类型不支持面向对象的编程机制,基本数据类型的数据也不具备对象的特性。(没有成员变量、方法可以被调用)。Java之所以提…...
五、传输层
(一)TCP传输控制协议 可靠的、面向连接的字节流服务,全双工,有端口寻址功能 1、TCP的三种机制 1.使用序号对分段的数据进行标记,便于调整数据包 2.TCP使用确认、校验和和定时器系统提供可靠性 3.TCP使用可变大小的…...
Thinkphp 6.0一对一关联查询
本节课我们来了解关联模型中,一对一关联查询的使用方法。 一.hasOne 模式 1. hasOne 模式,适合主表关联附表,具体设置方式如下: hasOne(关联模型,[外键,主键]); return $this->hasOne(Profile::class,user_id, id); 关联模型&…...
基于51单片机的自动打铃打鸣作息报时系统AT89C51数码管三极管时钟电路
wx供重浩:创享日记 对话框发送:单片机打铃 获取完整无水印论文报告说明(含源码程序、电路原理图和仿真图) 本次设计中的LED数码管电子时钟电路采用24小时制记时方式,本次设计采用AT89C51单片机的扩展芯片和6个PNP三极管做驱动&…...
算法详解-双指针算法的魅力-一种简单而高效的编程思想
文章目录双指针简介快慢指针快慢指针介绍快慢指针例题快慢指针优缺点:对撞指针对撞指针介绍:对撞指针例题对撞指针优缺点:更新中——未完总结更多宝藏双指针简介 😎🥳😎🤠😮&#x…...
网页审查元素
在讲解爬虫内容之前,我们需要先学习一项写爬虫的必备技能:审查元素(如果已掌握,可跳过此部分内容)。1、审查元素在浏览器的地址栏输入URL地址,在网页处右键单击,找到检查。(不同浏览器的叫法不同…...
gpt2 adapter finetune
1. 安装依赖: pip install -U adapter-transformers pip install datasets 2.训练代码: from datasets import load_dataset from transformers import AutoModelForCausalLM from transformers import GPT2Tokenizer from transformers import Adap…...
Day14_文件操作
一、数据存储 1.1 计算机数据存储 计算机内存分为运行内存和硬盘两种:保存在运行内存中的数据在程序运行结束后会自动释放,保存在硬盘中的数据会一直存在(除非手动删除或者硬盘损坏) 1)打开文件 open(文件路径, 文件打开方式‘r’, encod…...
leetcode 轮转数组 189
题目 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2…...
Leetcode.1849 将字符串拆分为递减的连续值
题目链接 Leetcode.1849 将字符串拆分为递减的连续值 Rating : 1747 题目描述 给你一个仅由数字组成的字符串 s。 请你判断能否将 s拆分成 两个或者多个 非空子字符串 ,使子字符串的 数值 按 降序 排列,且每两个 相邻子字符串 的数值之 差 …...
Android布局层级过深为什么会对性能有影响?为什么Compose没有布局嵌套问题?
做过布局性能优化的同学都知道,为了优化界面加载速度,要尽可能的减少布局的层级。这主要是因为布局层级的增加,可能会导致测量时间呈指数级增长。 而Compose却没有这个问题,它从根本上解决了布局层级对布局性能的影响: Compose界…...
【UR机械臂CB3 网络课程 】
【UR机械臂CB3 网络课程 】1. 前言2. 概览:特色与术语2.1 机器人组成2.1.1控制柜2.1.2 UR 机器人手臂2.2 接通机器人电源2.3 移动机械臂3. 机器人如何工作3.1 选择臂端工具3.2 输入有关臂端工具的信息3.3 连接外部装置3.4 机器人编程4. 设置工具4.1 末端执行器配置4.2 工具中心…...
dp-统计字典序元音字符串的数目
给你一个整数 n,请返回长度为 n 、仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量。 字符串 s 按 字典序排列 需要满足:对于所有有效的 i,s[i] 在字母表中的位置总是与 s[i1] 相同或在 s[i1] 之前。 示例 1: 输入&…...
LFM雷达实现及USRP验证【章节3:连续雷达测距测速】
第一章介绍了在相对速度为0时候的雷达测距原理 目录 1. LFM测速 1.1 雷达测速原理 1.2 Chrip信号测速 2. LFM测速代码实现 参数设置 仿真图像 matlab源码 代码分析 第一章介绍了在相对速度为0时候的雷达测距原理,第二章介绍了基于LFM的雷达测距原理及其实现…...
COLMAP多视角视图数据可视化
这篇博文主要介绍多视角三维重建的实用工具COLMAP。为了让读者更快确定此文是否为自己想找的内容,我先用简单几句话来描述此文做的事情: 假设我们针对一个物体(人)采集了多个(假设60个)视角的照片ÿ…...
2023年全国最新高校辅导员精选真题及答案36
百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 92.校园文化形成与发展的主要影响因素有() A.学校的领导与管理活…...
ThreeJS-全屏和退出全屏、自适应大小(五)
下载新得组件 npm install gsap -S 新引入 import gsap from gsap //动画控制 代码: <template> <div id"three_div"> </div> </template> <script> import * as THREE from "three"; import {OrbitControls } f…...
平面设计公司赚钱吗/北京seo产品
学到了最后一小节了,是关于Numpy的内容。numpy是针对多维数组的一个科学计算包。数组是相同类型数据类型的元素按照一定顺序排列的组合,而且必须是同数据类型的,比如全是整数、字符串或者其他。生成一般数组生成特殊类型数组生成随机数组数组…...
网站开发的投标案例/口碑营销的优势
在JAVA中,反射是极其重要的知识,在后期接触的大量框架的底层都 都运用了反射技术,因此掌握反射技术将帮助我们更好地理解这些框架的原理,以便灵活地掌握框架技术的使用。 1、认识Class类 JAVA反射的源头是class类,若…...
app网站怎么制作/百度云资源
给定一幅彩色图像,它由$mtimes n$的像素$A[1cdots m,1cdots n]$构成,每个像素是一个红绿蓝$(RGB)$亮度的三元组。假定我们希望轻度压缩这幅图像。具体地,我们希望从每一行中删除一个像素,使得图像变窄一个像素。 为了避免影响视觉…...
长沙网站建设公司哪家好/网站关键词怎么快速上排名
06/01 2020 日论文提交,我是国内普通211本科毕业专业计算机科学与技术,本科毕业后直接来英国读博士,由于本科期间并没有认真学习,导致直博第一年压力巨大,前前后后花了5年时间完成博士论文,中间的进步提升是…...
济南做网站的公司哪家好/ks数据分析神器
最近实现一个算法要用到求逆等矩阵运算,在网上搜到一个别人写的矩阵类,试了一下效果不错,贴在这里,做个保存。 matrix.h文件: 1 #ifndef __MATRIX_H__2 #define __MATRIX_H__3 4 #pragma once5 6 #include <iostrea…...
济南网站制作企业/湛江seo
2019独角兽企业重金招聘Python工程师标准>>> public class Test { public static void main(String[] args) { int i 0; i i ;System.out.println(i);} } 答案是 0 如果是 i i 就会是1 参考 https://blog.csdn.net/lxlmycsdnfree/article/details/80578222 其…...