之前总结的一些面试题

Java基础

基本类型

Long byte int double float boolean char short

String不可变的好处

可以缓存hash

String pool的需要

安全性

线程安全

ArrayList、LinkedList的异同

1.ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。

2.对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。

3.对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。

Hashmap和hashtable的区别

  1. HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。 2.HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
  2. 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。 HashMap不能保证随着时间的推移Map中的元素次序是不变的。

 

Hashmap源码解析

hashmap怎么解决哈希冲突:

链地址法,hash 表的每个元素又分别链接着一个单链表,元素为头结点,如果不同的 key 映射到了相同的下标,那么就使用头插法,插入到该元素对应的链表。

 

ConcurrentHashMap

为什么要使用ConcurrentHashMap:

1.多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。

2.HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。

ConcurrentHashMap原理:

采用分段锁技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段,ConcurrentHashMap基于concurrentLevel划分出了多个Segment来对key-value进行存储,从而避免每次锁定整个数组,在默认的情况下,允许16个线程并发无阻塞的操作集合对象,尽可能地减少并发时的阻塞现象。

死锁的原因和解锁

死锁原理

 死锁的四个必要条件:
互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

举例说明:  资源A,B 进程C,D

资源A,B都是不可剥夺资源:一个进程申请了之后,不能强制收回,只能进程结束之后自动释放。内存就是可剥夺资源

进程C申请了资源A,进程D申请了资源B

接下来C的操作用到资源BD的资源用到资源A。但是C,D都得不到接下来的资源,那么就引发了死锁。

避免死锁:

  1. 避免出现循环
  2. 减少持有资源的时间,较少锁竞争
  3. 使用较低的隔离级别

Sleep和wait的区别:

1sleep来自Thread类,wait来自Object类。
2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断。
3、使用范围:waitnotifynotifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 
4
sleep必须捕获异常,而waitnotifynotifyAll不需要捕获异常

Java中的String,StringBuilder,StringBuffer三者的区别

运行速度:StringBuilder > StringBuffer > String

原因:Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。StringBuilderStringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。

在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

java中四种修饰符的限制范围

访问权限      子类  其他包

   public     ∨   ∨    ∨     ∨          (对任何人都是可用的)

   protect    ∨   ∨   ∨     ×    (继承的类可以访问以及和private一样的权限)

   default    ∨   ∨    ×      ×    (包访问权限,即在整个包内均可被访问)

   private    ∨   ×     ×      ×    (除类型创建者和类型的内部方法之外的任何人都不能访问的元素)

 

线程池

好处:

1.降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

2.提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。

3.提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

线程池各个参数:

corePoolSize:线程池的核心线程数。

maximumPoolSize:线程池所能容纳的最大线程数。当活动线程(核心线程+非核心线程)达到这个数值后,后续任务将会根据 RejectedExecutionHandler 来进行拒绝策略处理。

keepAliveTime:闲置线程存活时间。超过该时长,非核心线程就会被回收。若线程池通过 allowCoreThreadTimeOut() 方法设置 allowCoreThreadTimeOut 属性为 true,则该时长同样会作用于核心线程,AsyncTask 配置的线程池就是这样设置的。

TimeUnit:时间单位

workQueue:线程池中的任务队列,通过线程池的 execute() 方法提交的 Runnable 对象会存储在该队列中。

threadFactory:线程工厂

rejectHandler:当任务无法被执行时(超过线程最大容量 maximum 并且 workQueue 已经被排满了)的处理策略,这里有四种任务拒绝类型。

线程池工作原则

1、当线程池中线程数量小于 corePoolSize 则创建线程,并处理请求。

2、当线程池中线程数量大于等于 corePoolSize 时,则把请求放入 workQueue ,随着线程池中的核心线程们不断执行任务,只要线程池中有空闲的核心线程,线程池就从workQueue 中取任务并处理。

3 、当 taskQueue 已存满,放不下新任务时则新建非核心线程入池,并处理请求直到线程数目达到 maximumPoolSize(最大线程数量设置值)。

4、如果线程池中线程数大于 maximumPoolSize 则使用 RejectedExecutionHandler 来进行任务拒绝处理。

线程之间的通信方式

  1. 同步。通过synchronized关键字实现线程通信
  2. 管道通信,使用java.io.PipedInputStream java.io.PipedOutputStream进行通信,通过管道,将一个线程中的消息发送给另一个。
  3. wait/notify机制

BIONIO

Java BIO 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

Java NIO 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

BIONIO适用场景分析:

BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

Redis

redis和memcached的区别

1memcache还可用于缓存其他东西,例如图片、视频等等;

2Redis不仅仅支持简单的k/v类型的数据,同时还提供listsethash等数据结构的存储;

3虚拟内存--Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;

4过期策略:memcacheset时就指定。Redis可以通过例如expire 设定;

5Memcached 不支持分布式,只能通过在客户端使用一致性哈希来实现分布式存储,这种方式在存储和查询时都需要先在客户端计算一次数据所在的节点。Redis Cluster 实现了分布式的支持。

6Redis 支持两种持久化策略:RDB 快照和 AOF 日志,而 Memcached 不支持持久化。

7灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;

8、应用场景不一样:Redis出来作为NoSQL数据库使用外,还能用做消息队列、数据堆栈和数据缓存等;Memcached适合于缓存SQL语句、数据集、用户临时性数据、延迟查询数据和session等。

数据淘汰策略

使用 Redis 缓存数据时,为了提高缓存命中率,需要保证缓存数据都是热点数据。可以将内存最大使用量设置为热点数据占用的内存量,然后启用 allkeys-lru 淘汰策略,将最近最少使用的数据淘汰。

持久化

RDB 持久化

将某个时间点的所有数据都存放到硬盘上。

可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。

如果系统发生故障,将会丢失最后一次创建快照之后的数据。

如果数据量很大,保存快照的时间会很长。

AOF 持久化

将写命令添加到 AOF 文件的末尾。

使用 AOF 持久化需要设置同步选项,从而确保写命令什么时候会同步到磁盘文件上。这是因为对硬盘的文件进行写入并不会马上将内容同步到磁盘文件上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到硬盘。有以下同步选项:

  • always 选项会严重减低服务器的性能;
  • everysec 选项比较合适,可以保证系统奔溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响;
  • no 选项并不能给服务器性能带来多大的提升,而且也会增加系统奔溃时数据丢失的数量。

7.为什么使用消息队列

1、异步:消息堆积能力;发送方接收方不需同时在线,发送方接收方不需同时扩容(削峰)。

3、解耦:防止引入过多的API给系统的稳定性带来风险;调用方使用不当会给被调用方系统造成压力,被调用方处理不当会降低调用方系统的响应能力。

4、复用:一次发送多次消费

5、可靠:一次保证消息的传递。如果发送消息时接收者不可用,消息队列会保留消息,直到成功地传递它;

6、提供路由:发送者无需与接收者建立连接,双方通过消息队列保证消息能够从发送者路由到接收者,甚至对于本来网络不易互通的两个服务,也可以提供消息路由。

Spring

Spring工作流程:

  1. spring mvc的所有请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求进行真正的处理工作。
    2.DispatcherServlet查询一个或多个HandlerMapping,找到处理请求的Controller. 
    3.DispatcherServlet
    请求提交到目标Controller 
    4.Controller
    进行业务逻辑处理后,会返回一个ModelAndView 
    5.Dispathcher
    查询一个或多个ViewResolver视图解析器,找到ModelAndView对象指定的视图对象 
    6.
    视图对象负责渲染返回给客户端。

 

BeanFactory 和 ApplicationContext 的区别(Spring两个容器):

1. BeanFactory:(org.springframework.beans.factory.BeanFactory 接口定义)提供了基本的 DI 支持。最常用的 BeanFactory 实现就是 XmlBeanFactory 类,它根据 XML 文件中的定义加载 beans,该容器从 XML 文件读取配置元数据并用它去创建一个完全配置的系统或应用。

2. ApplicationContext 应用上下文:org.springframework.context.ApplicationContext)基于 BeanFactory 之上构建,并提供面向应用的服务。

@transactional注解在什么情况下会失效,为什么

1、检查你方法是不是public

2、你的异常类型是不是unchecked异常 
如果我想check异常也想回滚怎么办,注解上面写明异常类型即可

@Transactional(rollbackFor=Exception.class)

类似的还有norollbackFor,自定义不回滚的异常

3、数据库引擎要支持事务,如果是MySQL,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的

4、是否开启了对注解的解析

5spring是否扫描到你这个包,如下是扫描到org.test下面的包

<context:component-scan base-package="org.test" ></context:component-scan>

  1. 检查是不是同一个类中的方法调用(如a方法调用同一个类中的b方法) 
    7
    、异常是不是被你catch住了

 

持久层框架

Mybatis

缓存:分为1级缓存和2级缓存。1级缓存在session中,2级缓存在sessionfactory中。

 

Jvm

线程私有

  1. 程序计数器

如果线程正在执行的是Java 方法,则这个计数器记录的是正在执行的虚拟机字节码指令地址

如果正在执行的是Native 方法,则这个技术器值为空(Undefined)

此内存区域是唯一一个在Java虚拟机规范中没有规定任何内存溢出情况的区域。

  1. 虚拟机栈

它描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直至完成的过程,就对应着一个栈帧在虚拟机栈中入栈和出栈的过程。
虚拟机栈帧中,局部变量表是比较为人所熟知的,也就是平常所说的“栈”,局部变量表所需的内存空间在编译期间分配完成,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
虚拟机栈有两种异常情况:

StackOverflowError:线程请求的栈深度大于虚拟机所允许的深度,特别是方法的递归调用时

OutOfMemoryError:虚拟机栈无法满足线程所申请的空间需求,即使经过动态扩展仍然无法满足,那么将导致OutOfMemoryError错误

 

3.本地方法栈

本地方法栈与虚拟机栈相似,不过服务于本地方法,有些虚拟机将这两个区域合二为一。
本地方法栈中抛出异常的情况与虚拟机栈相同。

 

共享内存区域

堆是Java虚拟机管理的内存中最大的一块,被所有线程共享,在虚拟机启动时创建,堆的作用就是存储对象实例。

堆也是垃圾收集器所管理的主要区域,因此很多时候也被称作“GC堆”。从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,因此堆还可以被细分为:新生代和老年代。再继续细分可以分为:Eden空间、From Survivor空间、To Survivor空间等

堆可以是物理上不连续的空间,只要逻辑上是连续的即可,-Xmx和-Xms参数可以控制堆的最大和最小大小。
    堆的空间大小不满足时将抛出OutOfMemoryError异常。

2.方法区(Method Area)

用于存储已被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等数据。Java虚拟机规范将方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆)。

方法区同样会抛出OutOfMemoryError异常。

 

 

  1. Jvm垃圾回收

Gc的历史要比Java久远

JVM的内存结构包括五大区域:

程序计数器、虚拟机栈、本地方法栈、堆区、方法区。

其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生、随线程而灭。

垃圾收集器在对堆区和方法区进行回收

判断对象是否存活的算法:

1.引用计数器算法

Jdk1.2之前,使用用用计数器算法。当这个类被加载到内存以后,就会产生方法区,堆栈、程序计数器等一系列信息,当创建对象的时候,为这个对象在堆栈空间中分配对象,同时会产生一个引用计数器,同时引用计数器+1,当有新的引用的时候,引用计数器继续+1,而当其中一个引用销毁的时候,引用计数器-1,当引用计数器被减为零的时候,标志着这个对象已经没有引用了,可以回收了

  1. 分代采集算法

它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代和新生代,在堆区之外还有一个代就是永久代。老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

  1. Gc Root

以一系列名为 GC Root的对象作为起点,从这些节点开始往下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链的时候,则就证明此对象是不可用的。

什么样的对象能成为GC Root 虚拟机中的引用的对象、方法区中的类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中jni的引用对象。

 

GC回收的对象都有哪些特征

1.超出作用域的对象/引用计数为空的对象。

2.GC Root开始搜索,且搜索不到的对象

3.root搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。

  1. 类加载的过程

加载、验证、准备、解析、初始化。然后是使用和卸载了

通过全限定名来加载生成class对象到内存中,然后进行验证这个class文件,包括文件格式校验、元数据验证,字节码校验等。准备是对这个对象分配内存。解析是将符号引用转化为直接引用(指针引用),初始化就是开始执行构造器的代码

  1. Spring事务

Spring事务 的本质其实就是数据库对事务的支持。使用Spring的事务管理功能后,我们可以不再写开启事务和提交回滚事务,而是由Spirng 自动完成。

隔离级别:

数据库

1.读写分离

主服务器用来处理写操作以及实时性要求比较高的读操作,而从服务器用来处理读操作。

读写分离常用代理方式来实现,代理服务器接收应用层传来的读写请求,然后决定转发到哪个服务器。

MySQL 读写分离能提高性能的原因在于:

主从服务器负责各自的读和写,极大程度缓解了锁的争用;

从服务器可以配置 MyISAM 引擎,提升查询性能以及节约系统开销;

增加冗余,提高可用性。

2.数据库切分

水平切分

水平切分又称为 Sharding,它是将同一个表中的记录拆分到多个结构相同的表中。

当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓存单个数据库的压力。

垂直切分

垂直切分是将一张表按列切分成多个表,通常是按照列的关系密集程度进行切分,也可以利用垂直切分将经常被使用的列和不经常被使用的列切分到不同的表中。

在数据库的层面使用垂直切分将按数据库中表的密集程度部署到不同的库中,例如将原来的电商数据库垂直切分成商品数据库 payDB、用户数据库 userDB 等。

 

innodbmyisam的区别

Innodbmysql默认引擎

Innodb支持事务,myisam不支持

Myisam只支持表级锁,innodb支持行级锁

Myisam不支持外键,innodb支持外键

Myisam适合查询非常频繁的场景,查询速度比innodb速度快

数据库三大范式:

第一范式:字段是最小的的单元不可再分

第二范式:满足第一范式,表中的字段必须完全依赖于全部主键而非部分主键。

第三范式:满足第二范式,非主键外的所有字段必须互不依赖

悲观锁与乐观锁

悲观锁:

每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。JavasynchronizedReentrantLock等独占锁就是悲观锁思想的实现。

乐观锁

每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Javajava.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

乐观锁的两种实现方式

1. 版本号机制

一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。

  1. CAS算法

数据库几种不同的事务隔离级别

READ_UNCOMMITTED未授权读取最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

READ_COMMITTED授权读取允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

REPEATABLE_READ可重复读对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

SERIALIZABLE串行最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

这里需要注意的是:Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.

Mysq优化

1、开启查询缓存,优化查询

2、explain你的select查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的

3、当只要一行数据时使用limit 1,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据

4、为搜索字段建索引

5、使用 ENUM 而不是 VARCHAR,如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是VARCHAR。

6、Prepared StatementsPrepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击

7、垂直分表

8、选择正确的存储引擎

 

计算机网络

UDPTCP

 UDP是无连接的,尽最大可能交付,没有拥塞控制,面向报文,支持一对一、一对多、多对一和多对多的交互通信。

TCP是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流,每一条 TCP 连接只能是点对点的(一对一)。

三次握手

假设 A 为客户端,B 为服务器端。

首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。

A B 发送连接请求报文段。

B 收到连接请求报文段,如果同意建立连接,则向 A 发送连接确认报文段。

A 收到 B 的连接确认报文段后,向 B 发出确认。

B 收到 A 的确认后,连接建立。

四次挥手

A 发送连接释放报文段。

B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向  B 发送数据。

B 不再需要连接时,发送连接释放请求报文段。

A 收到后发出确认,进入 TIME-WAIT 状态,等待最大报文存活时间后释放连接。

B 收到 A 的确认后释放连接。

 三次握手原因:

主要是为了防止已失效的连接请求报文突然到达服务器,造成服务器的等待和资源的浪费。

  1. Docker理解:

一、为什么使用Docker:

1.一致的运行环境

Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现这段代码在我机器上没问题啊这类问题。

2.更快速的启动时间

可以做到秒级、甚至毫秒级的启动时间。大大的节约了开发、测试、部署的时间。

3.隔离性

避免公用的服务器,资源会容易受到其他用户的影响。

4.迁移方便:

可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。

 

 

线程安全的单例模式:

 

冒泡排序代码:

import java.util.Arrays;

 public class BubbleSort {

public static void main(String[] args) {

for(int i=0;i<array.length;i++){  //表示n次排序过程。

    for(int j=0;j<array.length-1-i;j++){  

        if(array[j] > array[j+1]){  //前面的数字大于后面的数字就交换

            int temp = a[j];  

//两个元素交换位置

            a[j] = a[j+1];  

            a[j+1] = temp;  

        }   

    }  

}   

for(int x:array){  

    System.outprintln(x);  

}  

 

HTTP:

当输入www.baidu.com时,发生了哪些事情:

1.域名解析

2.tcp3次握手建立连接

3.建立连接后,发起http请求

4.服务器端响应http请求,浏览器得到到http请求的内容;

5.浏览器解析html代码,并请求html代码中的资源

6.浏览器对页面进行渲染,展现在用户面前。

 

微服务A       微服务B网关         微服务B

 

双重检查单例模式

猜你喜欢

转载自blog.csdn.net/weixin_38261597/article/details/89000244