15
1、Nacos与Eureka的区别
nacos 和eureka的范围不同,nacos的阀值是针对某个具体Service的,而不是针对所有的服务的;但Eureka的自我保护阀值是针对所有服务的。nacos支持cp和Ap俩种;eureka支持AP。nacos使用netty,是长连接;eureka是短连接,定时发送。
Eureka和Nacos的保护方式不同: Eureka保护方式:在短时间内,统计续约失败的比例,如果达到一定的阀值,则会触发自我保护的机制。在该机制下,Eureka Server 不会剔除任何的微服务,等到正常后,在退出自我保护机制。
2、Nacos与服务之间怎么保持通讯,服务宕机又重新恢复如何通知nacos
3、Ribbon的负载均衡算法有哪几种,如果要自定义手写一个负载均衡你的思路是怎么样的
ribbon主要负责请求分发,例如一个服务节点集群:多台服务器部署着订单服务,用户请求过来了就要根据不同的负载策略分发请求到不同机器上,起到一个缓解请求压力的作用。其自身不会发起请求,真正发起请求的还是Feign/openFeign。
ribbon是属于客户端的负载均衡,Nginx是属于服务端的负载均衡。
ribbon 负载均衡算法有七种:
1,RoundRobinRule轮询(默认):具体实现是一个负载均衡算法:第N次请求%服务器集群的总数=实际调用服务器位置的下标。
2:RandomRule随机
3:RetryRule轮询重试(重试采用的默认也是轮询)
4:WeightedResponseTimeRule响应速度决定权重
5:BestAvailableRule最优可用(底层也有RoundRobinRule);
6:AvailabilityFilteringRule可用性过滤原则
7:ZoneAvoidanceRule区域内可用性能最优
4、微服务集群环境下接口限流怎么实现
5、场景题:权限部分已经校验完token信息,现在feign与feign之间的调用,我要传递token参数,你有什么解决方案,方法
中绑定入参token或者对象加token字段或者对象去继承一个有token属性的父类,这些我觉得改动太大,如果有1000方法都要传递
这肯定是不行的,你看看有没有什么方案或者思路在改动较小的情况下解决问题
6、场景题:不使用七牛云等文件服务器的情况下,feign与feign之间去传文件,发现文件根本传不过去,接收方得到的文件是null
这种情况下该怎么解决
7、你们分库分表是怎么分的,分表的字段基于什么考虑,shareding-jdbc分表原理
8、为什么分页查询会越来越慢,我们经常用的百度查询,分页参数只有上一页和下一页为什么百度不会给用户展示首页和尾页的按钮
9、场景题:我现在mysql某张表数据量很大(2亿)的情况下怎么用java代码把数据导到另外一个库,不能借用第三方数据迁移工具,
java程序要怎么设计才能性能最优?
10、场景题:现在nacos服务部署在公用的服务器上,如果下面的开发都去连接这台公共的nacos服务,
这就相当于形成了一个集群,如果开发要调试自己写的代码,很可能请求会被负载均衡路由到其他同事的电脑,
所以我们开发一般会在自己的电脑启动一个本地的nacos,再把服务器上nacos的配置文件拷贝过来,请问有没有什么办法
可以彻底根治这个问题?保证开发不需要启动本地的nacos,在连接公共的nacos时依然能够保证每个人发起的请求最终都会在
自己的电脑上响应而不影响他人?允许改动相关分布式组件源码的基础上,说说你的解决方案和思路
11、RabbitMQ怎么保证投递消息不丢失
RabbitMQ一般情况下很少丢失,但是不能排除意外,为了保证我们自己的系统高可用,我们必须做好完善的措施,保证系统的稳定性。
1,消息持久化
2,ACK确认机制
3,设置集群镜像模式
4,消息补偿机制
第一种: 消息持久化
RabbitMQ 的消息默认存放在内存上面,如果不特别声明设置,消息不会持久化保存到硬盘上面的,如果节点重启或者意外crash掉,消息就好丢失。所以也要对消息进行持久化处理:1,Exchange 设置持久化,2,Queue进行持久化,3,Message持久化发送: 发送消息设置发送模式deliveryMode=2,代表持久化消息。
第二种: Ack确认机制
多个消费者同时收取消息,比如消息接收到一半的时候,一个消费者死掉了(逻辑复杂时间太长,超时了或者消费被停机了或者网络断开链接),为了保证消息不丢失就需要使用 Message acknowledgment机制,就是消费端消费完成要通知服务端,服务端才会把消息从内存删除。
这样就解决了,及时一个消费者出了问题,没有同步消息给服务端,还有洽谈的消费端去消费,保证了消息不丢的case.
第三种:设置集群镜像模式:
RabbitMQ有三种部署模式分别是:1,单节点模式: 最简单的情况,非集群的模式,节点挂了,消息就不能用了。业务可能瘫痪只能等待。
2,普通模式: 默认的集群模式,某个节点挂了,改节点上的消息不能用,有影响的业务瘫痪,只能等待节点恢复重启(必须持久化消息情况下)。
3,镜像模式:把需要的队列做成镜像队列,存在于多个节点,属于RabbitMQ的HA方案
第四种:消息补偿机制
12、场景题:mysql主从复制,读写分离的设计中,从库同步主 库会有一定延迟,如果现有这样一个场景,
在写入数据的时候,马上读取数据,怎么保证读取的数据不为空?达到即写即读的要求
13、谈谈Redission分布式锁的实现原理
Redission是redis客户端和jedis,lettuce一样,但他提供方诸多如分布式锁这些方便的工具。
实际上就是分三种情况作了处理
1. 如果锁不存在:使用hest方法创建了锁,filed是线程的唯一标识value是重入次数,初始为1
2,如果锁存在且为自身持有:使用hincrby将value加1表示了一次重入
3,如果锁存在但非自身持有: 返回锁的过期时间(毫秒级别)
watch dog 自动延期机制
在使用setnx实现的分布式锁中存在着一个这样的问题: 锁无法续期,在实际的业务中可能存在小锁中存在大事务的情况,如果事务的执行时间非常长,此次锁被已经超时释放掉了,就可能存在不可预料的问题产生。redission为我们提供的锁的默认时间是30秒,并且在客户端加锁成功后会启动一个watch dog 后台线程,没距离10秒检查一下,如果客户端还持有锁key,那么就不断的延长锁key生存时间。
1:redission自带的分布式锁作为附带的工具可以很好的满足我们在分布式系统上的加锁需求;
2:相较于setnx实现的分布式锁,其实现原理更为复杂一些,引入了watch dog机制,实现了锁的可续期,巧妙的利用hash 结构实现了锁的课重入;
3,无论是redission还是setnx实现的分布式锁,在redis的集群模式下,都存在主节点故障导致的问题;
A客户端在主节点写入自己的锁,此时主节点宕机,该数据未及时同步到从节点,而从节点被选为主节点,B客户端如果也去写入锁,同样也可以成功,此时存在并发写入导致的系列风险问题。
14、谈谈synchronized锁以及他的锁升级过程
synchronized在java中是一个关键字,他是由JVM实现的,所以Synchronized依赖于操作系统实现。但是Synchronized非常的智能,能通过判断整个程序的锁冲突来决定使用什么样的锁策略,对于程序员来说非常的友好。
首先synchronized的真个锁升级过程: 无锁-->偏向锁--->轻量级锁-->重量级锁,synchronized的升级过程就是以上四个步骤,当锁的竞争越来越激烈的时候synchronized会自动进行升级。
无锁: 整个程序都不会发生冲突的时候就是无锁策略。
偏向锁: 当我们的第一个线程拿到锁以后,系统会标记此线程,当此线程释放锁以后,在尝试拿锁会直接同行,并不需要直接加锁解锁操作。
轻量级锁: synchronized 升级成轻量级锁,这个轻量级锁就是一个基于cas实现的自旋锁,如果发现有锁冲突但是不严重的情况下,一个线程先获取到锁,然后另外一个线程也想要获取这个锁资源,这时候线程2不会进入进行阻塞等待,而是在CPU上空转,没有放弃CPU,然后每过一段时间就尝试获得锁,这可以使得在自旋的线程可以第一时间获取到锁资源,但是会占用CPU的资源。在我们的锁冲突比较不严重的情况下我们的synchronized就是这样的一个轻量级锁。
重量级锁:
当JVM判断我们整个程序的锁冲突严重的时候就会将synchronized升级成重量级锁,而这个重量级锁就是挂起等待锁。当一个线程获取到锁之后,其他线程会进入阻塞队列中等待,等待锁被释放,然后所有线程再去竞争锁,如果这个锁资源一直不被释放,其他线程就会一直在阻塞队列中一直死等,等到资源被释放。
synchronized只能进行锁升级,不能支持锁降级。
15、谈谈ReentrantLock锁的基本原理
一个线程持有锁时,当其他的线程尝试获取该锁时,会被阻塞;而这个线程尝试获取自己持有锁时,如果成功说明锁是可以重入的,反之则不可重入。
ReentrantLock使用内部类的Sync来管理锁,所以真正的获取锁是由Sync的实现类来控制的。Sync又有2个实现,分别为NonfairSync(非公平锁)和FairSync(公平锁)。Sync通过继承AQS实现,在AQS中维护了一个private volatile in state 来计算重入次数,避免频繁的持有释放操作带来的线程问题。
synchronized 关键字经过编译后,会在同步快的前后分别形成monitorenter和monitoreit2个字节码指令。每个锁对象内部维护一个计时器,该计时器初始值为0,表示任何线程都可以获取该锁并执行相应的方法。根据虚拟规范要求,在执行minitorenter指令时,首先尝试获取对象的锁,如果这个对象没有被锁定,或者当前线程已经拥有了对象的锁,把锁的计数器+1,相应的在执行monitorexit指令后锁计数器-1,当计数器为0时,锁就被释放,如果获取对象锁失败,那当前线程就要阻塞等待,直到对象锁被另一个线程释放为止。
16、ReentrantLock如何实现锁重入
一个线程持有锁时,当其他的线程尝试获取该锁时,会被阻塞;而这个线程尝试获取自己持有锁时,如果成功说明锁是可以重入的,反之则不可重入。
ReentrantLock使用内部类的Sync来管理锁,所以真正的获取锁是由Sync的实现类来控制的。Sync又有2个实现,分别为NonfairSync(非公平锁)和FairSync(公平锁)。Sync通过继承AQS实现,在AQS中维护了一个private volatile in state 来计算重入次数,避免频繁的持有释放操作带来的线程问题。
synchronized 关键字经过编译后,会在同步快的前后分别形成monitorenter和monitoreit2个字节码指令。每个锁对象内部维护一个计时器,该计时器初始值为0,表示任何线程都可以获取该锁并执行相应的方法。根据虚拟规范要求,在执行minitorenter指令时,首先尝试获取对象的锁,如果这个对象没有被锁定,或者当前线程已经拥有了对象的锁,把锁的计数器+1,相应的在执行monitorexit指令后锁计数器-1,当计数器为0时,锁就被释放,如果获取对象锁失败,那当前线程就要阻塞等待,直到对象锁被另一个线程释放为止
17、ReentrantLock中公平锁和非公平锁分别是怎么实现的
ReentrantLock是J.U.C包下的一个类,默认是非公平的。
public class ReentrantLock implements Lock, java.io.Serializable {
// 内部类
private final Sync sync;
public ReentrantLock() {
// 默认使用非公平锁
sync = new NonfairSync();
}
// 可通过传入参数(true)的形式使用公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
其中内部类 Sync 继承了AQS
abstract static class Sync extends AbstractQueuedSynchronizer {
//...
}
而 NonfairSync 与FairSync都是继承自Sync,也均是内部类
static final class NonfairSync extends Sync
static final class FairSync extends Sync
一.非公平锁实现原理
ReentranLock的常用实现方式: 一般都是直接new一个对象,然后通过lock()方法获取锁,
// 1. 获取对象,默认非公平
public ReentrantLock() {
sync = new NonfairSync();
}
// 2. 调用lock() 方法
public void lock() {
sync.lock();
}
// 3. 调用非公平内部类实现的 Lock() 方法
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
final void lock() {
// 尝试获取锁
if (compareAndSetState(0, 1))
// 获取成功后设置当前线程信息
setExclusiveOwnerThread(Thread.currentThread());
else
// 未获取到锁则执行以下方法
acquire(1);
}
// 其他方法。。。
}
// acquire(1) 方法内部逻辑
public final void acquire(int arg) {
if (!tryAcquire(arg) && // 尝试获取锁
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))// 调用AQS 同步方法
selfInterrupt();
}
非公平锁的 acquire(int arg) ,逻辑比较简单,源码如下
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 若锁状态为0,则直接执行获取锁逻辑
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 若锁已经有线程执行,则判断是否为当前线程,若是则state + 1, 这也是可重入的实现
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
二: 公平锁的实现原理:
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 与非公平锁的区别是加入了阻塞队列的判断
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
ReentrantLock 引入了阻塞队列来实现排队等候,先来先执行,后来则排队,所以是公平的,
ReentLock的非公平锁就是不考虑阻塞队列的情况下直接获取锁。
18、自旋锁和自适应自旋锁有什么区别
自旋锁的概念: 阻塞或唤醒一个java线程需要操作系统切换cpu状态来完成,这种状态装换需要耗费处理器的时间。如果同步代码块中的内容过于简单,状态转换消耗的时间有可能比用户执行代码的时间还要长。
在许多场景下,同步资源的锁定时间较短,为了这一小段时间去切换线程,线程挂起和恢复线程花费可能会让系统得不偿失。如果物理机器有多个处理器,能让2个或者多个线程同时并行执行。我们可以让后面那个请求锁的线程不放弃cpu的执行时间,看看持有锁的线程是否会很快就会释放锁。
而为了让当前线程 "稍等一下",我们需要让当前线程锁自旋,如果在自旋完成后前面锁定同步资源的线程已经释放了锁,那么当前线程不必阻塞而是直接获取同步资源,从而避免切换线程的开销。这就是自旋锁。
自旋锁的缺点: 自旋锁本身是有缺点的,他不能代替阻塞,自旋等待虽然避免了线程切换的开销,但是他要占用cpu处理器的时间,如果锁被占用的时间很短,自旋等待的效果就会非常好。反之,如果锁被占用的时间很长,那么自旋的线程只会白浪费处理器的资源。所以,自旋等待的时间必须要有一定的限度,如果自旋超过了限定次数(默认是10次,可以用 -XX:PreBlockSpin来更改)没有成功获得锁,就应该挂起线程。自旋锁的原理同样也是cas。
适应性自旋锁:自适应意味着自旋的时间(次数)不在固定,而是由前一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定。如果在同一个锁对象上,自旋等待刚刚成功获得过锁,并且持有锁的线程正在执行中,那么虚拟机就会认为这次自旋也是很有可能再次成功,进而他讲允许自旋等待的持续相对更长的时间。如果对于某个锁,自旋很少成功获得过,那子啊以后尝试获取这个锁时将可能省略自旋过程,直接阻塞线程,避免浪费处理器资源。
19、AQS了解吗?说说你的理解
AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到对列中
CLH(Craig,Landin,and Hagersten)对列是一个虚拟的双向对列(虚拟的双向对列即不存在对列的实例,仅存在节点之间的关联关系)。AQS是将每条请求共享资源的线程封装成一个CLH锁对列的一个节点(NODE),来实现锁的分配。
AQS 使用一个int 成员变量来表示同步状态,通过内置的FIFO对列来完成获取资源线程的排队工作。AQS使用CAS对该同步状态进行原子操作实现其对值的修改。
private volatile int state;//共享变量,使用volatile修饰保证线程可见性。
状态信息通过protected类型的getState,setState,compareAndSetState进行操作
//返回同步状态的当前值
protected final int getState() {
return state;
}
// 设置同步状态的值
protected final void setState(int newState) {
state = newState;
}
//原子地(CAS操作)将同步状态值设置为给定值update如果当前同步状态的值等于expect(期望值)
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
2, AQS对资源的共享方式
AQS定义2种资源共享方式
Exclusive(独占): 只有一个线程能执行,如ReentrantLock。又可以分为公平锁和非公平锁:
公平锁:按照线程在对列中的排队序列,先到者先拿到锁。
非公平锁:当线程要获取锁时,无视对列顺序直接去抢锁,谁抢到就是谁的
share(共享):多个线程可同时执行,如Semaphore/CountDownLatch,Semaphore,CountDownLatch,CyclicBarrier,ReadWriteLock。
ReentrantReadWriteLock 可以看成是组合式,因为ReentrantReadWriteLock 也就是读写锁允许多个线程同时对某一个资源进行行读。
不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取和释放方式即可,至于具体线程等待对列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。
3,AQS底层使用了模板方法模式
同步器的设计是基于模板方法模式的,如果需要自定义同步器一般是这样
使用者继承AbstractQueuedSynchronizer 并重写指定的方法(对共享资源state的获取和释放)
将aqs组合在自定义同步组件的实现中,并调用其模板方法,而这些模板方法会调用使用者重写的方法。
AQS使用了模板方法模式,自定义同步器时需要重写下面几个AQS提供的模板方法:
isHeldExclusively()//该线程是否正在独占资源。只有用到condition才需要去实现它。
tryAcquire(int)//独占方式。尝试获取资源,成功则返回true,失败则返回false。
tryRelease(int)//独占方式。尝试释放资源,成功则返回true,失败则返回false。
tryAcquireShared(int)//共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true,失败则返回false。
默认情况下每个方法都抛出UnsupportedOperationException.这些方法的实现必须是内部线程安全的,并且通常应简短而不是阻塞。AQS类中的其他方法都是final,所以无法被其他类使用,只有这几个方法可以被其他类使用。
以ReentrantLock为例,state初始化为0,表示未锁定状态,A线程
20、springcloud框架中,我们写的controller是线程安全的吗?@autowired注解注入的bean是类的成员变量,
请问他是线程安全的吗?如果是它是怎么保证安全的?如果不是为什么我们还要这样写不安全的代码?
21、spring事务失效的几种场景说说看
21、spring中如何将原来的事务挂起重新开启一个新事务?
22、乐观锁和悲观锁有什么区别?
乐观锁和悲观锁都是用于解决并发场景下的数据竞争问题,但是却是2种不同的思想。他们的使用非常的广泛,也不局限于某种语言或者数据库。
乐观锁的概念: 乐观锁指的是在操作数据的时候非常的乐观,乐观的认为被人不会同时修改数据,因此乐观锁默认不会上锁的,只有在执行更新的时候才会去判断在此期间别人是否修改了数据,如果别人修改了数据则放弃操作,否则执行操作。,
冲突比较少的时候,使用乐观锁,由于乐观锁的不上锁特性,所有在性能方面要比悲观锁好,比较适合在db的读大于写的业务场景。
悲观锁的概念:悲观锁指的是在操作数据库的时候比较悲观,悲观的认为别人一定会同时修改数据,因此悲观锁在操作数据库的时候是直接把数据上锁的,直到操作完成后才会释放锁,在上锁期间其他人不能操作数据。
冲突比较多的时候,使用悲观锁对于每一次数据修改都要上锁,如果在db读取需要比较大的情况下有线程在执行数据修改操作会导致读操作全部被挂载起来,等修改线程释放了锁才能读取到数据,体验感差。所以 比较适合用在db写大于读的时候
读取频繁使用乐观锁,写入频繁使用悲观锁。
乐观锁的实现方式:
乐观锁的实现方式主要有2种,一种是cas(Compare and Swap,比较并交换)机制,一种是版本号机制。
CAS机制:
CAS操作包括了三个操作数,分别是需要读取的内存位置(V)、进行比较的预期值(A)和拟写入的新值(B),操作逻辑是,如果内存位置V的值等于预期值A,则将该位置更新为新值B,否则不进行操作。另外,许多CAS操作都是自旋的,意思就是,如果操作不成功,就会一直重试,直到操作成功为止。
版本号机制:
版本号机制的基本思路,是在数据中增加一个version字段用来表示该数据的版本号,每当数据被修改版本号就会加1。当某个线程查询数据的时候,会将该数据的版本号一起读取出来,之后在该线程需要更新该数据的时候,就将之前读取的版本号与当前版本号进行比较,如果一致,则执行操作,如果不一致,则放弃操作
悲观锁的实现方式:
悲观锁的实现方式也就是加锁,加锁既可以在代码层面(比如java中的关键字synchronized关键字),也可以在数据库层面(比如MySQL中的排它锁)。
乐观锁和悲观锁并没有优劣之分,他们有各自的适合场景。
23、volatile是如何实现可见性和有序性的
24、有没有用过java泛型,谈谈你对泛型的理解以及它的应用场景
25、一个类中两个有@Async注解的方法互相调用,请问会不会出现失效的问题?为什么?
26、redis有哪些数据类型
27、场景题:现在有A有100条数据,B有200条数据,要把A和B中重复的数据找出来,用Redis的那种数据类型?
28、场景题:如果现在要统计一个班级的学生分数排行用Redis的那种数据类型?
29、Redis如何保证数据不丢失
30、Redis中AOF和RDB有什么区别
31、Redis在开启AOF和RDB持久化的情况下,还是会存在数据丢失的情况,我们该怎么办,这些数据1s都不能丢
32、Redis怎么保证数据同步问题
33、Redis的集群(cluster模式)环境是怎么实现数据同步的?
34、场景题:商品秒杀环境下,100万用户下单抢夺10件件商品,怎么保证商品的库存不出现超卖并且cpu还不能飙高?
34、场景题:用户下单购买商品,如果超过30分钟没有支付,该笔订单作废,这个功能该怎么设计?
35、谈谈分布式架构中hystrix的熔断机制
36、Sentinel的流控模式有哪几种
37、场景题:如用户支付时需要修改订单状态,同时用户要查询订单。
查询和修改操作会争抢数据库锁,产生竞争。业务需求是优先支付和更新订单的业务,
因此当修改订单业务触发阈值时,需要对查询订单业务限流,这种场景下需要使用Sentinel的哪种流控模式?
38、JWT技术如何实现活跃用户token过期自动续期,做到用户无感知,而不活跃的用户token过期则提示他重新登录
39、场景题:一款app首页加载很慢,要5分钟才能全部加载出来,首页有10多个模块一直在转圈圈,
请你设计一个优化方案如何修改java代码(不考虑前端),才能提升用户体验(提示:数据库,java多线程)
40、场景题:现在有个模块的查询很慢,sql语句的where条件是动态的,是一条动态sql
一定存在不走索引的情况,请你用你能想到的所有方法进行优化(不能将mysql表的所有字段都加索引),提升
查询性能
41、场景题:mysql某张表有5000万数据,分页查询,每次查1000条,发现越到后面就越慢,需要的时间越来越久,
后面几页直接查不出来了数据库连接超时,请问为什么会这样原因是什么?这种情况要怎么优化?
42、java 中动态加载和静态加载有什么区别?new 一个对象是动态还是静态?
class.forName("")是动态加载类,而 new class() 是静态加载类。本质区别是,静态加载类的时候编译时类必须存在,而动态加载时候类不一定存在。
43、String类型有最大长度吗?
String 的长度是有限制的。
编译期的限制: 字符串的utf-8编码指的字节数不能超过65535,字符串的长度不能超过65534;
运行时的限制: 字符串的长度不能超过2^31-1,占用的内存数不能超过虚拟机能够提供的最大值。
44、java是面向对象的语言,请问在java中那些不是对象?
java 是面向对象的语言,但是java中有些不是对象。
基本类型不是对象,boolean char short int long float double 的值都不是对象。
但是所有的数组类型,无论是对象数组还上班基本类型的数据都扩展了object类
java 不是一种纯面向对象的语言。
45、java中接口可以多继承接口吗?
在java编程语言中,java接口是一种抽象类型,是抽象方法的集合。接口通常以interfance来声明。并且java接口对于程序的运行有重大的意义。java接口可以继承多个接口,具体还有以下说明:
1,一个接口可以继承多个接口,
2, 一个类可以实现多个接口;
3,一个类只能继承一个类,这就是java的继承特点。
接口的继承使用extends关键字
46、抽象类可以继承普通类吗?
抽象类可以继承普通类,抽象类与普通类的区别仅仅是抽象类本身不能实例化和允许含有抽象方法,必须通过有其他类继承他来工作。除此之外没有其他的特殊方法。