赞
踩
public class SingletonDemo {
private static volatile SingletonDemo instance = null;
public SingletonDemo(){
System.out.println(Thread.currentThread().getName()+"\t 我是构造方法SingletonDemo() ");
}
public static SingletonDemo getInstance(){
if(instance == null){
//同步代码块 加锁前后判断
synchronized (SingletonDemo.class){
if(instance == null){
instance = new SingletonDemo();
}
}
}
return instance;
}
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
new Thread(() -> {
SingletonDemo instance = SingletonDemo.getInstance();
System.out.println(instance);
}, String.valueOf("线程" + i)).start();
}
}
}
需求分析—需求初审----分析业务需求----设计uml图(主要类图和用例图(在线流程图工具,如:爱莫))----编写相应模块的概要设计文档--------测试库创建表(设计规范和原则)----业务代码编写—代码提交git------对接前端进行vue页面渲染------功能测试—对接测试进行测试--------根据bug编号自己模块bug-----对接测试进行测试-------测试通过-------版本上线----周末组员分享会
uml图熟练掌握。
1、功能差异
模块 | Nacos | Eureka | 说明 |
---|---|---|---|
注册中心 | 是 | 是 | 服务治理基本功能,负责服务中心化注册 |
配置中心 | 是 | 否 | Eureka需要配合Config实现配置中心,且不提供管理界面 |
动态刷新 | 是 | 否 | Eureka需要配合MQ实现配置动态刷新,Nacos采用Netty保持TCP长连接实时推送 |
分组 | 是 | 否 | Nacos可用根据业务和环境进行分组管理 |
元数据 | 是 | 是 | 提供服务标签数据,例如环境或服务标识 |
权重 | 是 | 否 | Nacos默认提供权重设置功能,调整承载流量压力 |
健康检查 | 是 | 是 | Nacos支持由客户端或服务端发起的健康检查,Eureka是由客户端发起心跳 |
负载均衡 | 是 | 是 | 均提供负责均衡策略,Eureka采用Ribion |
管理界面 | 是 | 否 | Nacos支持对服务在线管理,Eureka只是预览服务状态 |
2、选型建议
采用Eureka方案的考虑
采用Nacos方案的考虑
3、cap方案(核心点)
补充zookeeper
而其中zookeeper采用的是集中式集群中的一主多从方案,为的是提升性能和可用性,但是有人就问了,这个不是高可用么,为什么不是AP系统呢。我这里举个场景:有3个节点的zookeeper集群(节点分别为:1、2、3),其中一个业务配置了其中一个节点3,假设节点3跟另外两个节点网络断开,也就是出现了脑裂,那么这个时候节点3还能对外提供服务么?不能,因为zookeeper为了防止脑裂问题,做了限制,就导致节点3是无法再对外提供服务,即使业务节点和3节点之间的网络是OK的也不行。但是整个zookeeper集群的其他节点对外仍然是可用的,但是这个不行,那么这个就叫不可用。因而就不能满足AP
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(如syn=1)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的包(SYN=1),同时自己也发送一个SYN包,如SYN包内容为:(SYN=1)+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据
rabbitMq 批量消费(pull 拉取模式 ),消费端的限流
更多队列面试–参考队列高级特性
借助消息队列,将读写缓存的工作委托给第三方
思路:
读数据的人,在发现缓存中没有数据时,发消息给消息队列,然后自己查数据库(第一次),队列消费方收到要‘查数据’的信息时,微服务负责查询数据库然后存储到redis。 第二次缓存就有数据
写数据的人,在更新完数据库之后,同样发送消息给消息队列,队列消费方收到要‘删除缓存’的信息时,微服务负责去执行删除缓存操作,不再由它自己(生产方)来删除缓存,而是由『别人』来删除;
整个过程读和写操作,送到队列这是有先后的。即串行化执行。
好处:将并行化产生的问题,由串行化顺序执行
坏处:代价很大,一旦消息队列宕机,整个过程结束
1、Java.lang.NullPointerException 程序遇上了空指针
2、java.lang.ClassNotFoundException 指定的类不存在
3、java.lang.ArithmeticException 数学运算异常
4、java.lang.ArrayIndexOutOfBoundsException 数组下标越界
5. java.lang.IllegalArgumentException 方法的参数错误
6.java.lang.IllegalAccessException 没有访问权限
7.java.lang.InstantiationError 实例化错误,当一个应用试图通过Java的new操作符构造一个抽象类或者接口时抛出该异常
8.java.lang.StackOverflowError 堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出时抛出该错误
9.java.lang.NoSuchMethodError 方法不存在错误
10.java.lang.NumberFormatException 数字格式异常。当试图将一个String转换为指定的数字类型
11.java.sql.SQLException Sql语句执行异常
12.java.io.IOException 输入输出异常
13.org.apache.ibatis.binding.BindingException
14.executor.ExecutorException: Statement returned more than one row, where no more than one was expected.
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
400 Bad Request 客户端请求的语法错误,如参数类型错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
500:服务器内部错误。
501:不支持当前请求所需要的某个功能。
502:错误网关。
503:服务器不可用(超载或停机维护),只是暂时不可用。
504:网关超时。
505:HTTP版本不受支持。
UML是统一建模语言,是一种可视化的面向对象建模语言
https://blog.csdn.net/qq_40138785/article/details/81065979
使用 ES 对基础文档进行检索操作,如将传统的 word 文档、PDF 文档、PPT 文档等通过 Openoffice 或者 pdf2htmlEX 工具转换为 HTML,再将 HTML 以JSON 串的形式录入到 ES,以对外提供检索服务
ES 强大的全文检索功能实现,分词检索,效率比直接like 模糊查询高,而且es内部是使用反向键索引
谈谈观察模式??
了解eureka和zookeeper区别之前,我们先来了解一下这个知识,cap理论
1、C:Consistency 强一致性
Consistency:强一致性的意思就是说,我们读写数据必须是一摸一样的。
比如有一条数据 data1,分别存在A服务器和B服务器,通过程序连接A服务器,把data1修改为data2。此时如果我们访问A服务器该数据时data2。
当我们访问B服务器的时候,如果返回的还是未修改的data1,那么则不符合一致性,如果返回的是data2,则符合数据的一致性
2、A:Availability 高可用性
这个比较好理解,就是说,只要我对服务器,发送请求,服务器必须对我进行相应,保证服务器一直是可用的。
3、P:Partition tolerance 分区容错性
一般来说,分布式系统是分布在多个位置的。比如我们的一台服务器在北京,一台在上海。可能由于天气等原因的影响。造成了两条服务器直接不能互相通信,数据不能进行同步。这就是分区容错。我们认为,分区容错是不可避免的。也就是说 P 是必然存在的
4、为什么CAP只能达到 CP 或者 AP?
由以上我们得知,P是必然存在的。
如果我们保证了CP,即一致性与分布容错。当我们通过一个服务器修改数据后,该服务器会向另一个服务器发送请求,将数据进行同步,但此时,该数据应处于锁定状态,不可再次修改,这样,如果此时我们想服务器发送请求,则得不到相应,这样就不能A,高可用。
如果我们保证了AP,那么我们不能对服务器进行锁定,任何时候都要得到相应,那么数据的一致性就不好说了
5、eureka和zookeeper的cap理论
1、zookeeper是基于cp的,也就是强一致性和分区容错性
zookeeper会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新leader选举,问题在于选举leader时间太长,30-120s,且选举期间整个zookeeper集群都是不可用的,这样就导致在选举期间注册服务瘫痪.在漫长的选举过程中导致注册长期不可用是不能容忍的
2、eureka是基于ap的,也就是高可用性和分区容错性
eureka是基于ap的看明白了这一点,因此在设计时就优先保证高可用性。允许短暂的不一致性。
Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册时,如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka服务还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
1. Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
2. Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
3. 当网络稳定时,当前实例新的注册信息会被同步到其它节点中
因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪
举例子:比如在淘宝节那天,成千上万的访问进来,我们是用 eureka 还是 zookeeper ?比如,如果用zookeeper,在那天晚上00:00抢购的时候,zookeeper节点挂掉一部分,难道我们要等待zookeeper重新选举一个新的leader吗?情况想复杂点,如果00:00-00:30由于网络波动,zookeeper一直选举是不是淘宝节就不过了 ?当然这种情况几乎不存在,zookeeper依然能够胜任,只是理想状态。但是作为架构师,在选择上是不是就要优先考虑 可用性了。
那什么情况下,可以考虑使用zookeeper呢 ?zookeeper除了服务注册与发现的功能外,还可以用于分布式锁上,保证数据一定准确,但是在服务注册与发现的功能上,推荐使用eureka
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
1、浅拷贝
A a = new A("zhangsan");
B b = new B(20);
a.bb = b;
A c = a; //a和c是指向同一块内存地址
2、深拷贝
方法一:使用Jackson序列化进行深拷贝
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private Address address;
public static void main(String[] args) throws JsonProcessingException {
Address address = new Address("杭州", "中国");
User user = new User("大山", address);
ObjectMapper objectMapper = new ObjectMapper();
User copyUser = objectMapper.readValue(objectMapper.writeValueAsString(user), User.class);
System.out.println(user == copyUser);
System.out.println(copyUser.getAddress().getCity());
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Address {
private String city;
private String country;
}
方法二:Apache Commons Lang序列化
@Data
@AllArgsConstructor
public class User implements Serializable{
private String name;
private Address address;
public static void main(String[] args) throws JsonProcessingException {
Address address = new Address("杭州", "中国");
User user = new User("大山", address);
User copyUser = (User) SerializationUtils.clone(user);
System.out.println(user == copyUser);
System.out.println(copyUser.getAddress().getCity());
}
}
@Data
@AllArgsConstructor
class Address implements Serializable {
private String city;
private String country;
}
高到低:application.proerties----->bootstrap.yml------->application.yml
1、关系操作符 ==
基本类型:比较的就是值是否相同
引用类型:比较的就是地址值是否相同
String a = "aa";
String b = "aa";
System.out.println(a == b); //true 常量池的原因 a和b指向相同
String c = new String("aa");
String d = new String("aa");
System.out.println(c == d); //false
2、equals
引用类型:默认情况下,比较的是地址值
Integer a = 3;
Integer b = 5;
System.out.println(a.equals(b)); //false
String c = new String("aa");
String d = new String("aa");
System.out.println(c.equals(d)); //true String 类重写了 equals 方法:先判断引用是否相同(是否为同一对象),如果不是在判断内容是否一致
我们可以得出结论,尽管父类equals是比较对象的地址,但是我们常常重写equals方法来比较对象内容,这才是设计equals()的真正目的
public class AAA {
private String name;
public AAA(String name){
this.name = name;
}
@Override
public boolean equals(Object obj) {
AAA a = (AAA)obj;
return this.name == a.name;
}
public static void main(String[] args) {
AAA a = new AAA("zhangsan");
AAA b = new AAA("zhangsan");
System.out.println(a.equals(b));
}
}
3、hashCode
hashCode() 方法是基类Object中的 **实例native方法**,因此对所有继承于Object的类都会有该方法
在 Java 中,由 Object 类定义的 hashCode 方法会针对不同的对象返回不同的整数。(这是通过将该对象的内部地址转换成一个整数来实现的, HashCode 只是在需要用到哈希算法的数据结构中才有用,比如 HashSet, HashMap 和 Hashtable,在集合中存放一个元素到集合往往先判断hashcode是否相同,然后再调用equals来比较内容,来决定元素的存储位置
@DependsOn
注解可以用来控制bean的创建顺序,该注解用于声明当前bean依赖于另外一个bean。所依赖的bean会被容器确保在当前bean实例化之前被实例化
@Configuration
public class BeanOrderConfiguration {
@Bean
//@DependsOn("beanB")
public BeanA beanA( ){
System.out.println("bean A init");
return new BeanA();
}
@Bean
public BeanB beanB(){
System.out.println("bean B init");
return new BeanB();
}
@Bean
@DependsOn({"beanD","beanE"})
public BeanC beanC(){
System.out.println("bean C init");
return new BeanC();
}
@Bean
@DependsOn("beanE")
public BeanD beanD( ){
System.out.println("bean D init");
return new BeanD();
}
@Bean
public BeanE beanE(){
System.out.println("bean E init");
return new BeanE();
}
}
class BeanA{ }
class BeanB{}
class BeanC{ }
class BeanD{ }
class BeanE{ }
在@Bean
标注的方法上,如果你传入了参数,springboot会自动会为这个参数在spring上下文里寻找这个类型的引用。并先初始化这个类的实例
@Bean
//@DependsOn("beanB")
public BeanA beanA(BeanB beanB ){
System.out.println("bean A init");
return new BeanA();
}
@Bean
public BeanB beanB(){
System.out.println("bean B init");
return new BeanB();
}
说明:几个误区
在标注了@Configuration的类中,写在前面的@Bean一定会被先注册吗?
这个不存在的,spring在以前xml的时代,也不存在写在前面一定会被先加载的逻辑。因为xml不是渐进的加载,而是全部parse好,再进行依赖分析和注册。到了springboot中,只是省去了xml被parse成spring内部对象的这一过程,但是加载方式并没有大的改变
利用@Order这个标注能进行加载顺序的控制吗?
严格的说,不是所有的Bean都可以通过
@Order
这个标注进行顺序的控制。你把@Order
这个标注加在普通的方法上或者类上一点鸟用都没有,一般用@Order比较多的地方
- 控制AOP的类的加载顺序,也就是被
@Aspect
标注的类- 控制
ApplicationListener
实现类的加载顺序- 控制
CommandLineRunner
实现类的加载顺序- 控制过滤器的加载顺序
用来指定配置文件的加载顺序@AutoConfigureOrder
@AutoConfigureOrder
只能改变外部依赖的@Configuration
的顺序。如何理解是外部依赖呢。能被你工程内部scan到的包,都是内部的Configuration,而spring引入外部的Configuration,都是通过spring特有的spi文件:
spring.factories;换句话说@AutoConfigureOrder能改变
spring.factories中的
@Configuration的顺序
1、在并发量不高的情况下,而且对象没有成员变量,如springmvc,这个时候没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存,应该用单例bean
2、如果是在高并发情况下,为了防止并发问题;即一个请求改变了对象的状态(所谓对象的状态:就是对象的属性的变化),此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理;
当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例
public class Sum {
public static int sum(int[] arr) {
return sum(arr, 0);
}
private static int sum(int[] arr, int l) {
if (l == arr.length)
return 0;
return arr[l] + sum(arr, l + 1);
}
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println(sum(nums));
}
}
1、String:String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁,正因为String是不可变类,所以是线程安全的
String a = "123";
a = "456";
System.out.println(a);
看到这里,不明白了,这不是明明已经对他进行修改了吗?为什么还说他是一个不可变类呢?
可以看出来,再次给a赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“456”这个字符串,a则指向最新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。 所以经常改变内容的字符串最好不要用 String
2、StringBuffer 字符串变量(线程安全),StringBuilder 字符串变量(非线程安全),当对字符串进行修改的时候,特别是字符串对象经常改变的情况下,需要使用 StringBuffer 和 StringBuilder 类,和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象
如下案例:
StringBuffer b = new StringBuffer("123");
b.append("456");
// b打印结果为:123456
System.out.println(b);
IO流是做什么的?流的分类?常用的流有哪些?
IO流指的是输入输出流,用来处理设备上的数据,这里的设备指硬盘、内存、键盘录入、网络传输等。
1、BIO (blocking I/O)
在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程响应,如果没有则会一直等待或者遭到拒绝请求。
实现模式:BIO是同步并阻塞,服务器实现模式是一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善
适应场景:
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高
2、NIO (non-blocking I/O)
主要是用来解决BIO的大并发问题,因为在BIO中,如果要同时处理多个客户端请求,就必须使用多线程来处理。也就是说,将每一个客户端请求分配给一个线程来单独处理。这样做虽然可以达到我们的要求,但同时又会带来另外一个问题。由于每创建一个线程,就要为这个线程分配一定的内存空间(也叫工作存储器),而且操作系统本身也对线程的总数有一定的限制。如果客户端的请求过多,服务端程序可能会因为不堪重负而拒绝客户端的请求,甚至服务器可能会因此而瘫痪
实现模式:NIO是同步非阻塞,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理;最重要的地方是当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面,所以所有的连接只需要一个线程就可以搞定。
适应场景:NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持
3、AIO
与NIO不同,当进行读写操作时,只须直接调用API的read或write方法即可。这两种方法均为异步的,对于读操作而言,当有流可读取时,操作系统会将可读的流传入read方法的缓冲区,并通知应用程序;对于写操作而言,当操作系统将write方法传递的流写入完毕时,操作系统主动通知应用程序。 即可以理解为,read/write方法都是异步的,完成后会主动调用回调函数。 在JDK1.7中,这部分内容被称作NIO.2,主要在java.nio.channels包下增加了下面四个异步通道:
- AsynchronousSocketChannel
- AsynchronousServerSocketChannel
- AsynchronousFileChannel
- AsynchronousDatagramChannel
其中的read/write方法,会返回一个带回调函数的对象,当执行完读取/写入操作后,直接调用回调函数
Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持
Stringbuilder的 append
bootstrap.yml 先于 application.yml 加载,bootstrap.yml高优先级加载不会被后续覆盖的。原因是:类加载器的先后顺序
bootstrap.yml(bootstrap.properties)可以理解成系统级别的一些参数配置,应用于更加早期配置信息读取,这些参数一般是不会变动的
application.yml(application.properties) 可以用来定义应用级别的
另外在springcloud中,配置中心的配置要放在bootstrap.yml中
可以从内存,客户端获取了配置中心的配置信息以后,会将配置信息在本地内存中存储一份
1)请检测项目配置文件的名字是否为bootstrap.yml,检查配置文件中spring.application.name属性的值是否与配置中心的data-id名相同
2)配置中心的配置信息缩进以及空格写的格式是否正确.
3)没有下载好依赖
4)配置文件名字bootstrap.yml没有修改
5)配置中心的dataId名字是否正确
6)检查分组是否正确
7)配置的名字是否正确,缩进关系是否正确
8)假如是动态发布,类上是否有@RefreshScope注解
能会经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则
服务端口,服务名,服务的注册地址
为了考虑性能我们的服务一般首先会从内存读取配置信息,同时我们的微服务还可以定时向nacos配置中心发请求拉取(pull)更新的配置信息,但是在一定时间间隔内还可能会出现不一致的配置,所以nacos服务端而言,当配置变化时,会通知客户端然后更新客户端
nacos2.0之前nacos客户端采用长轮询机制拉取nacos服务的配置信息,每隔30秒pull+“push,在服务端的配置信息变更以后,通知服务端中处于等待状态的客户端队列中的客户端对象,并更新客户端对应的响应数据,然后返回响应
34、redis过期会瞬间删除key吗?
35、分布式锁的分库分表问题?
26、阿里算法
/**
* 1、现输入一个字符串,对字符串进行压缩,如:如字符串"abcdabcd"由于无连续重复字符,压缩后的字符串还是"abcdabcd",字符串"xxxrryyyyyyz"压缩后就成为"3x2r6yz"。
static char[] stringZip(char InputStr[],char OutputStr[]){
if(InputStr==null||InputStr.length==0){
return null;
}
int num=1;
int j=0;
int len=InputStr.length;
for(int i=0;i<InputStr.length;i++){
if((InputStr[i]==InputStr[i+1])&&(InputStr[i]!='\0')){
num++;
if(i==(len-2)){
OutputStr[j++]=(char)(num+'0');
OutputStr[j++]=InputStr[i];
break;
}
}
else{
if(num>1){
OutputStr[j++]=(char)(num+'0');
OutputStr[j++]=InputStr[i];
num=1;
}else{
OutputStr[j++]=InputStr[i];
}
}
}
return OutputStr;
}
public static void main(String[] args) {
char[] InputStr={'a','a','a','b','a','b','c','c','c'};
char[] OutputStr=new char[InputStr.length];
char[] out2=stringZip(InputStr,OutputStr);
for(int i=0;i<out2.length;i++){
System.out.print(out2[i]);
}
//SpringApplication.run(SpringSecurity22DemoApplication.class, args);
}
* 2、150个线程同时向一个银行账户中存入1元钱。
*
* 3、实现一个本地缓存。着重考虑3个方面:1.缓存作为公共服务,线程安全如何保证;2.缓存数据到期,要如何清理;3.缓存容量满了,如何淘汰已有元素,存入新元素。
*/
BIO 和NIO NIO 有哪些选择器
se{
OutputStr[j++]=InputStr[i];
}
}
}
return OutputStr;
}
public static void main(String[] args) {
char[] InputStr={'a','a','a','b','a','b','c','c','c'};
char[] OutputStr=new char[InputStr.length];
char[] out2=stringZip(InputStr,OutputStr);
for(int i=0;i<out2.length;i++){
System.out.print(out2[i]);
}
//SpringApplication.run(SpringSecurity22DemoApplication.class, args);
}
*
\* 2、150个线程同时向一个银行账户中存入1元钱。
*
\* 3、实现一个本地缓存。着重考虑3个方面:1.缓存作为公共服务,线程安全如何保证;2.缓存数据到期,要如何清理;3.缓存容量满了,如何淘汰已有元素,存入新元素。
*/
BIO 和NIO NIO 有哪些选择器
hashcode怎么算的
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。