备案网站内容格式填写建设婚纱摄影网站的费用

当前位置: 首页 > news >正文

备案网站内容格式填写,建设婚纱摄影网站的费用,怎么提高网站关键词排名,免费刷推广链接的网站JDK 和 JRE 有什么区别#xff1f;JDK#xff1a;java 开发工具包#xff0c;提供了 java 的开发环境和运行环境。JRE#xff1a;java 运行环境#xff0c;为 java 的运行提供了所需环境。JDK 其实包含了 JRE#xff0c;同时还包含了编译 java 源码的编译器 javac#x… JDK 和 JRE 有什么区别JDKjava 开发工具包提供了 java 的开发环境和运行环境。JREjava 运行环境为 java 的运行提供了所需环境。JDK 其实包含了 JRE同时还包含了编译 java 源码的编译器 javac还包含了很多 java 程序调试和分析的工具如果你需要运行 java 程序只需安装 JRE 就可以了如果你需要编写 java 程序需要安装 JDK。 和 equals 的区别是什么对于基本类型和引用类型 的作用效果是不同的基本类型比较的是值是否相同    引用类型比较的是引用是否相同String x string;String y string;String z new String(string);System.out.println(xy); // trueSystem.out.println(xz); // falseSystem.out.println(x.equals(y)); // trueSystem.out.println(x.equals(z)); // true两个对象的 hashCode()相同equals()不一定 true。在散列表中hashCode()相等即两个键值对的哈希值相等然而哈希值相等并不一定能得出键值对相等。final 在 java 中有什么作用final 修饰的类叫最终类该类不能被继承。final 修饰的方法不能被重写。final 修饰的变量叫常量常量必须初始化初始化之后值就不能被修改。 java 中的 Math.round(-1.5) 等于多少等于 -1因为在数轴上取值时中间值0.5向右取整所以正 0.5 是往上取整负 0.5 是直接舍弃。String 属于基础的数据类型吗String 不属于基础类型基础类型有 8 种byte、boolean、char、short、int、float、long、double而 String 属于对象。java 中操作字符串都有哪些类它们之间有什么区别操作字符串的类有String、StringBuffer、StringBuilder。String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象每次操作都会生成新的 String 对象然后将指针指向新的 String 对象而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作所以在经常改变字符串内容的情况下最好不要使用 String。StringBuffer 和 StringBuilder 最大的区别在于StringBuffer 是线程安全的而 StringBuilder 是非线程安全的但 StringBuilder 的性能却高于 StringBuffer所以在单线程环境下推荐使用 StringBuilder多线程环境下推荐使用 StringBuffer。String stri与 String strnew String(i)一样吗不一样因为内存的分配方式不一样。String stri的方式java 虚拟机会将其分配到常量池中而 String strnew String(i) 则会被分到堆内存中。如何将字符串反转使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。String 类的常用方法都有那些indexOf()返回指定字符的索引。charAt()返回指定索引处的字符。replace()字符串替换。trim()去除字符串两端空白。split()分割字符串返回一个分割后的字符串数组。getBytes()返回字符串的 byte 类型数组。length()返回字符串长度。toLowerCase()将字符串转成小写字母。toUpperCase()将字符串转成大写字符。substring()截取字符串。equals()字符串比较。抽象类必须要有抽象方法吗不需要抽象类不一定非要有抽象方法。普通类和抽象类有哪些区别普通类不能包含抽象方法抽象类可以包含抽象方法。抽象类不能直接实例化普通类可以直接实例化。抽象类能使用 final 修饰吗不能定义抽象类就是让其他类继承的如果定义为 final 该类就不能被继承这样彼此就会产生矛盾所以 final 不能修饰抽象类。接口和抽象类有什么区别实现抽象类的子类使用 extends 来继承接口必须使用 implements 来实现接口。构造函数抽象类可以有构造函数接口不能有。main 方法抽象类可以有 main 方法并且我们能运行它接口不能有 main 方法。实现数量类可以实现很多个接口但是只能继承一个抽象类。访问修饰符接口中的方法默认使用 public 修饰抽象类中的方法可以是任意访问修饰符。java 中 IO 流分为几种按功能来分输入流input、输出流output。按类型来分字节流和字符流。字节流和字符流的区别是字节流按 8 位传输以字节为单位输入输出数据字符流按 16 位传输以字符为单位输入输出数据。BIO、NIO、AIO 有什么区别BIOBlock IO 同步阻塞式 IO就是我们平常使用的传统 IO它的特点是模式简单使用方便并发处理能力低。NIONew IO 同步非阻塞 IO是传统 IO 的升级客户端和服务器端通过 Channel通道通讯实现了多路复用。AIOAsynchronous IO 是 NIO 的升级也叫 NIO2实现了异步非堵塞 IO 异步 IO 的操作基于事件和回调机制。Files的常用方法都有哪些Files.exists()检测文件路径是否存在。Files.createFile()创建文件。Files.createDirectory()创建文件夹。Files.delete()删除一个文件或目录。Files.copy()复制文件。Files.move()移动文件。Files.size()查看文件个数。Files.read()读取文件。Files.write()写入文件。Collection 和 Collections 有什么区别java.util.Collection 是一个集合接口集合类的一个顶级接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式其直接继承接口有List与Set。Collections则是集合类的一个工具类/帮助类其中提供了一系列静态方法用于对集合中元素进行排序、搜索以及线程安全等各种操作。HashMap 和 Hashtable 有什么区别hashMap去掉了HashTable 的contains方法但是加上了containsValue和containsKey方法。hashTable同步的而HashMap是非同步的效率上比hashTable要高。hashMap允许空键值而hashTable不允许。如何决定使用 HashMap 还是 TreeMap对于在Map中插入、删除和定位元素这类操作HashMap是最好的选择。然而假如你需要对一个有序的key集合进行遍历TreeMap是更好的选择。说一下 HashMap 的实现原理HashMap实际上是一个“链表散列”的数据结构即数组和链表的结合体。当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)。说一下 HashSet 的实现原理HashSet底层由HashMap实现HashSet的值存放于HashMap的key上HashMap的value统一为PRESENTArrayList 和 LinkedList 的区别是什么最明显的区别是 ArrrayList底层的数据结构是数组支持随机访问而 LinkedList 的底层数据结构是双向循环链表不支持随机访问。使用下标访问一个元素ArrayList 的时间复杂度是 O(1)而 LinkedList 是 O(n)。如何实现数组和 List 之间的转换List转换成为数组调用ArrayList的toArray方法。数组转换成为List调用Arrays的asList方法。ArrayList 和 Vector 的区别是什么Vector是同步的而ArrayList不是。然而如果你寻求在迭代的时候对列表进行改变你应该使用CopyOnWriteArrayList。 ArrayList比Vector快它因为有同步不会过载。 ArrayList更加通用因为我们可以使用Collections工具类轻易地获取同步列表和只读列表。Array 和 ArrayList 有何区别Array可以容纳基本类型和对象而ArrayList只能容纳对象。 Array是指定大小的而ArrayList大小不是固定的。 Array没有提供ArrayList那么多功能比如addAll、removeAll和iterator等。在 Queue 中 poll()和 remove()有什么区别poll() 和 remove() 都是从队列中取出一个元素但是 poll() 在获取元素失败的时候会返回空但是 remove() 失败的时候会抛出异常。哪些集合类是线程安全的vector就比arraylist多了个同步化机制线程安全因为效率较低现在已经不太建议使用。在web应用中特别是前台页面往往效率页面响应速度是优先考虑的。statck堆栈类先进后出。hashtable就比hashmap多了个线程安全。enumeration枚举相当于迭代器。并行和并发有什么区别并行是指两个或者多个事件在同一时刻发生而并发是指两个或多个事件在同一时间间隔发生。并行是在不同实体上的多个事件并发是在同一实体上的多个事件。在一台处理器上“同时”处理多个任务在多台处理器上同时处理多个任务。如hadoop分布式集群。所以并发编程的目标是充分的利用处理器的每一个核以达到最高的处理性能。线程和进程的区别进程是程序运行和资源分配的基本单位一个程序至少有一个进程一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元而多个线程共享内存资源减少切换次数从而效率更高。线程是进程的一个实体是cpu调度和分派的基本单位是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。守护线程是什么守护线程即daemon thread是个服务线程准确地来说就是服务其他的线程。创建线程有哪几种方式①继承Thread类创建线程类定义Thread类的子类并重写该类的run方法该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。创建Thread子类的实例即创建了线程对象。调用线程对象的start()方法来启动该线程。②通过Runnable接口创建线程类定义runnable接口的实现类并重写该接口的run()方法该run()方法的方法体同样是该线程的线程执行体。创建 Runnable实现类的实例并依此实例作为Thread的target来创建Thread对象该Thread对象才是真正的线程对象。调用线程对象的start()方法来启动该线程。③通过Callable和Future创建线程创建Callable接口的实现类并实现call()方法该call()方法将作为线程执行体并且有返回值。创建Callable实现类的实例使用FutureTask类来包装Callable对象该FutureTask对象封装了该Callable对象的call()方法的返回值。使用FutureTask对象作为Thread对象的target创建并启动新线程。调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。说一下 runnable 和 callable 有什么区别Runnable接口中的run()方法的返回值是void它做的事情只是纯粹地去执行run()方法中的代码而已Callable接口中的call()方法是有返回值的是一个泛型和Future、FutureTask配合可以用来获取异步执行的结果。线程有哪些状态线程通常都有五种状态创建、就绪、运行、阻塞和死亡。创建状态。在生成线程对象并没有调用该对象的start方法这是线程处于创建状态。就绪状态。当调用了线程对象的start方法之后该线程就进入了就绪状态但是此时线程调度程序还没有把该线程设置为当前线程此时处于就绪状态。在线程运行之后从等待或者睡眠中回来之后也会处于就绪状态。运行状态。线程调度程序将处于就绪状态的线程设置为当前线程此时线程就进入了运行状态开始运行run函数当中的代码。阻塞状态。线程正在运行的时候被暂停通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspendwait等方法都可以导致线程阻塞。sleep() 和 wait() 有什么区别sleep()方法是线程类Thread的静态方法让调用线程进入睡眠状态让出执行机会给其他线程等到休眠时间结束后线程进入就绪状态和其他线程一起竞争cpu的执行时间。因为sleep() 是static静态的方法他不能改变对象的机锁当一个synchronized块中调用了sleep() 方法线程虽然进入休眠但是对象的机锁没有被释放其他线程依然无法访问这个对象。wait()wait()是Object类的方法当一个线程执行到wait方法时它就进入到一个和该对象相关的等待池同时释放对象的机锁使得其他线程能够访问可以通过notifynotifyAll方法来唤醒等待的线程。notify()和 notifyAll()有什么区别如果线程调用了对象的 wait()方法那么线程便会处于该对象的等待池中等待池中的线程不会去竞争该对象的锁。当有线程调用了对象的 notifyAll()方法唤醒所有 wait 线程或 notify()方法只随机唤醒一个 wait 线程被唤醒的的线程便会进入该对象的锁池中锁池中的线程会去竞争该对象锁。也就是说调用了notify后只要一个线程会由等待池进入锁池而notifyAll会将该对象等待池内的所有线程移动到锁池中等待锁竞争。优先级高的线程竞争到对象锁的概率大假若某线程没有竞争到该对象锁它还会留在锁池中唯有线程再次调用 wait()方法它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行直到执行完了 synchronized 代码块它会释放掉该对象锁这时锁池中的线程会继续竞争该对象锁。线程的 run()和 start()有什么区别start()方法来启动一个线程真正实现了多线程运行。这时无需等待run方法体代码执行完毕可以直接继续执行下面的代码 这时此线程是处于就绪状态 并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态 这里方法run()称为线程体它包含了要执行的这个线程的内容 Run方法运行结束 此线程终止。然后CPU再调度其它线程。run()方法是在本线程里的只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已直接调用run()方法必须等待run()方法执行完毕才能执行下面的代码所以执行路径还是只有一条根本就没有线程的特征所以在多线程执行时要使用start()方法而不是run()方法。创建线程池有哪几种方式①.newFixedThreadPool(int nThreads)创建一个固定长度的线程池每当提交一个任务就创建一个线程直到达到线程池的最大数量这时线程规模将不再变化当线程发生未预期的错误而结束时线程池会补充一个新的线程。②. newCachedThreadPool()创建一个可缓存的线程池如果线程池的规模超过了处理需求将自动回收空闲线程而当需求增加时则可以自动添加新线程线程池的规模不存在任何限制。③. newSingleThreadExecutor()这是一个单线程的Executor它创建单个工作线程来执行任务如果这个线程异常结束会创建一个新的来替代它它的特点是能确保依照任务在队列中的顺序来串行执行。④. newScheduledThreadPool(int corePoolSize)创建了一个固定长度的线程池而且以延迟或定时的方式来执行任务类似于Timer。线程池中 submit()和 execute()方法有什么区别接收的参数不一样submit有返回值而execute没有submit方便Exception处理在 java 程序中怎么保证多线程的运行安全线程安全在三个方面体现原子性提供互斥访问同一时刻只能有一个线程对数据进行操作atomic,synchronized可见性一个线程对主内存的修改可以及时地被其他线程看到synchronized,volatile有序性一个线程观察其他线程中的指令执行顺序由于指令重排序该观察结果一般杂乱无序happens-before原则。多线程锁的升级原理是什么在Java中锁共有4种状态级别从低到高依次为无状态锁偏向锁轻量级锁和重量级锁状态这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。偏向锁、轻量级锁和重量级锁对比锁类型优点缺点适用场景偏向锁加锁、解锁不需要额外资源消耗效率较高如果线程间存在锁竞争会带来额外的解锁消耗适用只有一个线程访问同步块的情景轻量级锁竞争的线程不会阻塞提高了程序响应速度如果获取锁失败会进入自旋消耗cpu针对锁占用时间短对响应时间比较敏感的情况重量级锁线程竞争不使用自旋不消耗cpu线程会被阻塞影响响应时间锁占用时间较长对吞吐量要求较高什么是死锁死锁是指两个或两个以上的进程在执行过程中由于竞争资源或者由于彼此通信而造成的一种阻塞的现象若无外力作用它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁这些永远在互相等待的进程称为死锁进程。怎么防止死锁死锁的四个必要条件互斥条件进程对所分配到的资源不允许其他进程进行访问若其他进程访问该资源只能等待直至占有该资源的进程使用完成后释放该资源请求和保持条件进程获得一定的资源之后又对其他资源发出请求但是该资源可能被其他进程占有此事请求阻塞但又对自己获得的资源保持不放不可剥夺条件是指进程已获得的资源在未完成使用之前不可被剥夺只能在使用完后自己释放环路等待条件是指进程发生死锁后若干进程之间形成一种头尾相接的循环等待资源关系ThreadLocal 是什么有哪些使用场景线程局部变量是局限于线程内部的变量属于线程自身所有不在多个线程间共享。Java提供ThreadLocal类来支持线程局部变量是一种实现线程安全的方式。但是在管理环境下如 web 服务器使用线程局部变量的时候要特别小心在这种情况下工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放Java 应用就存在内存泄露的风险。说一下 synchronized 底层实现原理synchronized可以保证方法或者代码块在运行时同一时刻只有一个方法可以进入到临界区同时它还可以保证共享变量的内存可见性。Java中每一个对象都可以作为锁这是synchronized实现同步的基础普通同步方法锁是当前实例对象静态同步方法锁是当前类的class对象同步方法块锁是括号里面的对象synchronized 和 volatile 的区别是什么volatile本质是在告诉jvm当前变量在寄存器工作内存中的值是不确定的需要从主存中读取 synchronized则是锁定当前变量只有当前线程可以访问该变量其他线程被阻塞住。volatile仅能使用在变量级别synchronized则可以使用在变量、方法、和类级别的。volatile能实现变量的修改可见性、有序性不能保证原子性而synchronized则可以保证变量的修改可见性和原子性。volatile不会造成线程的阻塞synchronized可能会造成线程的阻塞。volatile标记的变量不会被编译器优化synchronized标记的变量可以被编译器优化。synchronized 和 Lock 有什么区别首先synchronized是java内置关键字在jvm层面Lock是个java类synchronized无法判断是否获取锁的状态Lock可以判断是否获取到锁synchronized会自动释放锁(a 线程执行完同步代码会释放锁 b 线程执行过程中发生异常会释放锁)Lock需在finally中手工释放锁unlock()方法释放锁否则容易造成线程死锁用synchronized关键字的两个线程1和线程2如果当前线程1获得锁线程2线程等待。如果线程1阻塞线程2则会一直等待下去而Lock锁就不一定会等待下去如果尝试获取不到锁线程可以不用一直等待就结束了synchronized的锁可重入、不可中断、非公平而Lock锁可重入、可判断、可公平两者皆可Lock锁适合大量同步的代码的同步问题synchronized锁适合代码少量的同步问题。synchronized 和 ReentrantLock 区别是什么synchronized是和if、else、for、while一样的关键字ReentrantLock是类这是二者的本质区别。既然ReentrantLock是类那么它就提供了比synchronized更多更灵活的特性可以被继承、可以有方法、可以有各种各样的类变量ReentrantLock比synchronized的扩展性体现在几点上 ReentrantLock可以对获取锁的等待时间进行设置这样就避免了死锁 ReentrantLock可以获取各种锁的信息ReentrantLock可以灵活地实现多路通知 说一下 atomic 的原理Atomic包中的类基本的特性就是在多线程环境下当有多个线程同时对单个包括基本类型及引用类型变量进行操作时具有排他性即当多个线程同时对该变量的值进行更新时仅有一个线程能成功而未成功的线程可以向自旋锁一样继续尝试一直等到执行成功。Atomic系列的类中的核心方法都会调用unsafe类中的几个本地方法。里面大量的方法调用都会存在安全隐患需要小心使用否则会导致严重的后果。什么情况下需要序列化a当你想把的内存中的对象状态保存到一个文件中或者数据库中时候b当你想用套接字在网络上传送对象的时候c当你想通过RMI传输对象的时候动态代理是什么有哪些应用当想要给实现了某个接口的类中的方法加一些额外的处理。比如说加日志加事务等。可以给这个类创建一个代理故名思议就是创建一个新的类这个类不仅包含原来类方法的功能而且还在原来的基础上添加了额外处理的新类。这个代理类并不是定义好的是动态生成的。具有解耦意义灵活扩展性强。动态代理的应用Spring的AOP加事务加权限加日志怎么实现动态代理首先必须定义一个接口还要有一个InvocationHandler(将实现接口的类的对象传递给它)处理类。再有一个工具类Proxy(习惯性将其称为代理类因为调用他的newInstance()可以产生代理对象,其实他只是一个产生代理对象的工具类。利用到InvocationHandler拼接代理类源码将其编译生成代理类的二进制码利用加载器加载并将其实例化产生代理对象最后返回。深拷贝和浅拷贝区别是什么浅拷贝只是复制了对象的引用地址两个对象指向同一个内存地址所以修改其中任意的值另一个值都会随之变化这就是浅拷贝。深拷贝是将对象及值复制过来两个对象修改其中任意的值另一个值不会改变这就是深拷贝。session 和 cookie 有什么区别Session是在服务端保存的一个数据结构用来跟踪用户的状态这个数据可以保存在集群、数据库、文件中Cookie是客户端保存用户信息的一种机制用来记录用户的一些信息也是实现Session的一种方式。说一下 session 的工作原理其实session是一个存在服务器上的类似于一个散列表格的文件。里面存有我们需要的信息在我们需要用的时候可以从里面取出来。类似于一个大号的map吧里面的键存储的是用户的sessionid用户向服务器发送请求的时候会带上这个sessionid。这时就可以从中取出对应的值了。如果客户端禁止 cookie 能实现 session 还能用吗不能因为Session是用Session ID来确定当前对话所对应的服务器Session而Session ID是通过Cookie来传递的禁用Cookie相当于失去了Session ID也就得不到Session了。throw 和 throws 的区别throws是用来声明一个方法可能抛出的所有异常信息throws是将异常声明但是不处理而是将异常往上传谁调用我就交给谁处理。而throw则是指抛出的一个具体的异常类型。final、finally、finalize 有什么区别final可以修饰类、变量、方法修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。finally一般作用在try-catch代码块中在处理异常的时候通常我们将一定要执行的代码方法finally代码块中表示不管是否出现异常该代码块都会执行一般用来存放一些关闭资源的代码。finalize是一个方法属于Object类的一个方法而Object类是所有类的父类该方法一般由垃圾回收器来调用当我们调用System的gc()方法的时候由垃圾回收器调用finalize(),回收垃圾。 常见的异常类有哪些NullPointerException当应用程序试图访问空对象时则抛出该异常。SQLException提供关于数据库访问错误或其他错误信息的异常。IndexOutOfBoundsException指示某排序索引例如对数组、字符串或向量的排序超出范围时抛出。 NumberFormatException当应用程序试图将字符串转换成一种数值类型但该字符串不能转换为适当格式时抛出该异常。FileNotFoundException当试图打开指定路径名表示的文件失败时抛出此异常。IOException当发生某种I/O异常时抛出此异常。此类是失败或中断的I/O操作生成的异常的通用类。ClassCastException当试图将对象强制转换为不是实例的子类时抛出该异常。ArrayStoreException试图将错误类型的对象存储到一个对象数组时抛出的异常。IllegalArgumentException抛出的异常表明向方法传递了一个不合法或不正确的参数。ArithmeticException当出现异常的运算条件时抛出此异常。例如一个整数“除以零”时抛出此类的一个实例。 NegativeArraySizeException如果应用程序试图创建大小为负的数组则抛出该异常。NoSuchMethodException无法找到某一特定方法时抛出该异常。SecurityException由安全管理器抛出的异常指示存在安全侵犯。UnsupportedOperationException当不支持请求的操作时抛出该异常。RuntimeException是那些可能在Java虚拟机正常运行期间抛出的异常的超类。简述 tcp 和 udp的区别TCP面向连接如打电话要先拨号建立连接;UDP是无连接的即发送数据之前不需要建立连接。TCP提供可靠的服务。也就是说通过TCP连接传送的数据无差错不丢失不重复且按序到达;UDP尽最大努力交付即不保证可靠交付。Tcp通过校验和重传控制序号标识滑动窗口、确认应答实现可靠传输。如丢包时的重发控制还可以对次序乱掉的分包进行顺序控制。UDP具有较好的实时性工作效率比TCP高适用于对高速传输和实时性有较高的通信或广播通信。每一条TCP连接只能是点到点的;UDP支持一对一一对多多对一和多对多的交互通信。TCP对系统资源要求较多UDP对系统资源要求较少。tcp 为什么要三次握手两次不行吗为什么为了实现可靠数据传输 TCP 协议的通信双方 都必须维护一个序列号 以标识发送出去的数据包中 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值 并确认对方已经收到了序列号起始值的必经步骤。如果只是两次握手 至多只有连接发起方的起始序列号能被确认 另一方选择的序列号则得不到确认。OSI 的七层模型都有哪些应用层网络服务与最终用户的一个接口。表示层数据的表示、安全、压缩。会话层建立、管理、终止会话。传输层定义传输数据的协议端口号以及流控和差错校验。网络层进行逻辑地址寻址实现不同网络之间的路径选择。数据链路层建立逻辑连接、进行硬件地址寻址、差错校验等功能。物理层建立、维护、断开物理连接。get 和 post 请求有哪些区别GET在浏览器回退时是无害的而POST会再次提交请求。GET请求会被浏览器主动cache而POST不会除非手动设置。GET请求只能进行url编码而POST支持多种编码方式。GET请求参数会被完整保留在浏览器历史记录里而POST中的参数不会被保留。GET请求在URL中传送的参数是有长度限制的而POST么有。对参数的数据类型GET只接受ASCII字符而POST没有限制。GET比POST更不安全因为参数直接暴露在URL上所以不能用来传递敏感信息。GET参数通过URL传递POST放在Request body中。如何实现跨域方式一JSONP跨域方式二CORS解释一下什么是 aopAOP是OOP的补充和完善。将那些与业务无关却为业务模块所共同调用的逻辑或责任封装起来便于减少系统的重复代码降低模块间的耦合度并有利于未来的可操作性和可维护性。使用“横切”技术AOP把软件系统分为两个部分核心关注点和横切关注点。业务处理的主要流程是核心关注点与之关系不大的部分是横切关注点。横切关注点的一个特点是他们经常发生在核心关注点的多处而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点将核心关注点和横切关注点分离开来。解释一下什么是 ioc把复杂系统分解成相互合作的对象这些对象类通过封装以后内部实现对外部是透明的从而降低了解决问题的复杂度而且可以灵活地被重用和扩展。IOC容器成了整个系统的关键核心它起到了一种类似“粘合剂”的作用把系统中的所有对象粘合在一起发挥作用如果没有这个“粘合剂”对象与对象之间会彼此失去联系。 spring 常用的注入方式有哪些Spring通过DI依赖注入实现IOC控制反转常用的注入方式主要有三种构造方法注入setter注入基于注解的注入spring 中的 bean 是线程安全的吗Spring容器中的Bean是否线程安全容器本身并没有提供Bean的线程安全策略因此可以说spring容器中的Bean本身不具备线程安全的特性但是具体还是要结合具体scope的Bean去研究。spring 支持几种 bean 的作用域当通过spring容器创建一个Bean实例时不仅可以完成Bean实例的实例化还可以为Bean指定特定的作用域。Spring支持如下5种作用域singleton单例模式在整个Spring IoC容器中使用singleton定义的Bean将只有一个实例prototype原型模式每次通过容器的getBean方法获取prototype定义的Bean时都将产生一个新的Bean实例request对于每次HTTP请求使用request定义的Bean都将产生一个新实例即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时该作用域才有效session对于每次HTTP Session使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时该作用域才有效globalsession每个全局的HTTP Session使用session定义的Bean都将产生一个新实例。典型情况下仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时该作用域才有效 spring 自动装配 bean 有哪些方式spring中bean装配有两种方式隐式的bean发现机制和自动装配在java代码或者XML中进行显示配置spring 事务实现方式有哪些编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法这就是编程式事务管理。基于 TransactionProxyFactoryBean 的声明式事务管理。基于 Transactional 的声明式事务管理。基于 Aspectj AOP 配置事务。说一下 spring 的事务隔离事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度当多个事务同时访问相同数据时如果没有采取必要的隔离机制就可能发生以下问题脏读一个事务读到另一个事务未提交的更新数据。幻读例如第一个事务对一个表中的数据进行了修改比如这种修改涉及到表中的“全部数据行”。同时第二个事务也修改这个表中的数据这种修改是向表中插入“一行新数据”。那么以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行就好象发生了幻觉一样。不可重复读比方说在同一个事务中先后执行两条一模一样的select语句期间在此次事务中没有执行过任何DDL语句但先后得到的结果不一致这就是不可重复读。幻读和不可重复读的区别?不可重复读重点是修改在同一事务中同样的条件第一次读的数据和第二次读的数据不一样。幻读重点在于新增或者删除在同一事务中同样的条件,第一次和第二次读出来的记录数不一样。MySQL如何解决不可重复读●MySQL中默认使用的事务隔离界别是可重复读为了解决不可重复读问题InnoDB采用了MVCC(多版本并发控制)【基于乐观锁】来解决●MVCC(多版本并发控制)是利用在每条数据后面加了隐藏的两列创建版本号和删除版本号每个事务在开始的时候都会有一个递增的当前事务版本号说一下 spring mvc 运行流程1. 用户向服务器发送请求请求被Spring 前端控制Servelt DispatcherServlet捕获2. DispatcherServlet对请求URL进行解析得到请求资源标识符URI。然后根据该URI调用HandlerMapping获得该Handler配置的所有相关的对象包括Handler对象以及Handler对象对应的拦截器最后以HandlerExecutionChain对象的形式返回   3. DispatcherServlet 根据获得的Handler选择一个合适的HandlerAdapter附注如果成功获得HandlerAdapter后此时将开始执行拦截器的preHandler(…)方法4.  提取Request中的模型数据填充Handler入参开始执行HandlerController)。5.  Handler执行完成后向DispatcherServlet 返回一个ModelAndView对象   6.  根据返回的ModelAndView选择一个适合的ViewResolver必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet 7. ViewResolver 结合Model和View来渲染视图 8. 将渲染结果返回给客户端。spring mvc 有哪些组件Spring MVC的核心组件DispatcherServlet中央控制器把请求给转发到具体的控制类Controller具体处理请求的控制器HandlerMapping映射处理器负责映射中央处理器转发给controller时的映射策略ModelAndView服务层返回的数据和视图层的封装类ViewResolver视图解析器解析具体的视图Interceptors 拦截器负责拦截我们定义的请求然后做处理工作RequestMapping 的作用是什么RequestMapping是一个用来处理请求地址映射的注解可用于类或方法上。用于类上表示类中的所有响应请求的方法都是以该地址作为父路径。为什么要用 spring bootSpring Boot使编码变简单Spring Boot使配置变简单Spring Boot使部署变简单Spring Boot使监控变简单spring boot 核心配置文件是什么properties文件yml文件spring cloud 的核心组件有哪些服务发现——Netflix Eureka客服端负载均衡——Netflix Ribbon断路器——Netflix Hystrix服务网关——Netflix Zuul分布式配置——Spring Cloud Configmybatis 中 #{}和 \({}的区别是什么#{}是预编译处理\){}是字符串替换Mybatis在处理#{}时会将sql中的#{}替换为?号调用PreparedStatement的set方法来赋值Mybatis在处理\({}时就是把\){}替换成变量的值使用#{}可以有效的防止SQL注入提高系统安全性。rabbitmq 的使用场景有哪些跨系统的异步通信所有需要异步交互的地方都可以使用消息队列。多个应用之间的松耦合的接口。应用内的同步变异步。rabbitmq 有哪些重要的角色生产者、消费者和代理。rabbitmq 有哪些重要的组件ConnectionFactory连接管理器Channel信道Exchange交换器Queue队列RoutingKey路由键BindingKey绑定键 rabbitmq 的消息是怎么发送的首先客户端必须连接到 RabbitMQ 服务器才能发布和消费消息客户端和 rabbit server 之间会创建一个 tcp 连接一旦 tcp 打开并通过了认证认证就是你发送给 rabbit 服务器的用户名和密码你的客户端和 RabbitMQ 就创建了一条 amqp 信道channel信道是创建在“真实” tcp 上的虚拟连接amqp 命令都是通过信道发送出去的每个信道都会有一个唯一的 id不论是发布消息订阅队列都是通过这个信道完成的。rabbitmq 怎么保证消息的稳定性提供了事务的功能。通过将 channel 设置为 confirm确认模式。rabbitmq 怎么避免消息丢失消息持久化ACK确认机制设置集群镜像模式消息补偿机制要保证消息持久化成功的条件有哪些声明队列必须设置持久化 durable 设置为 true.消息推送投递模式必须设置持久化deliveryMode 设置为 2持久。消息已经到达持久化交换器。消息已经到达持久化队列。rabbitmq 持久化有什么缺点持久化的缺点就是降低了服务器的吞吐量因为使用的是磁盘而非内存存储从而降低了吞吐量。可尽量使用 ssd 硬盘来缓解吞吐量的问题。rabbitmq 有几种广播类型三种广播模式fanout: 所有bind到此exchange的queue都可以接收消息纯广播绑定到RabbitMQ的接受者都能收到消息direct: 通过routingKey和exchange决定的那个唯一的queue可以接收消息topic:所有符合routingKey(此时可以是一个表达式)的routingKey所bind的queue可以接收消息 rabbitmq 怎么实现延迟消息队列通过消息过期后进入死信交换器再由交换器转发到延迟消费队列实现延迟功能使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。rabbitmq 集群有什么用集群主要有以下两个用途高可用某个服务器出现问题整个 RabbitMQ 还可以继续使用高容量集群可以承载更多的消息量。rabbitmq 节点的类型有哪些磁盘节点消息会存储到磁盘。内存节点消息都存储在内存中重启服务器消息丢失性能高于磁盘类型。rabbitmq 对集群节点停止顺序有要求吗RabbitMQ 对集群的停止的顺序是有要求的应该先关闭内存节点最后再关闭磁盘节点。如果顺序恰好相反的话可能会造成消息的丢失。kafka 可以脱离 zookeeper 单独使用吗为什么kafka 不能脱离 zookeeper 单独使用因为 kafka 使用 zookeeper 管理和协调 kafka 的节点服务器。kafka 有几种数据保留的策略有两种数据保存策略按照过期时间保留和按照存储的消息大小保留。什么情况会导致 kafka 运行变慢cpu 性能瓶颈磁盘读写瓶颈网络瓶颈使用 kafka 集群需要注意什么集群的数量不是越多越好最好不要超过 7 个因为节点越多消息复制需要的时间就越长整个群组的吞吐量就越低。集群数量最好是单数因为超过一半故障集群就不能用了设置为单数容错率更高。zookeeper 都有哪些功能集群管理监控节点存活状态、运行请求等。主节点选举主节点挂掉了之后可以从备用的节点开始新一轮选主主节点选举说的就是这个选举的过程使用 zookeeper 可以协助完成这个过程。分布式锁zookeeper 提供两种锁独占锁、共享锁。独占锁即一次只能有一个线程使用资源共享锁是读锁共享读写互斥即可以有多线线程同时读同一个资源如果要使用写锁也只能有一个线程使用。zookeeper可以对分布式锁进行控制。命名服务在分布式系统中通过使用命名服务客户端应用能够根据指定名字来获取资源或服务的地址提供者等信息。zookeeper 有几种部署模式有三种部署模式单机部署、集群部署、伪集群部署zookeeper 怎么保证主从节点的状态同步zookeeper 的核心是原子广播这个机制保证了各个 server 之间的同步。实现这个机制的协议叫做 zab 协议。 zab 协议有两种模式分别是恢复模式选主和广播模式同步。当服务启动或者在领导者崩溃后zab 就进入了恢复模式当领导者被选举出来且大多数 server 完成了和 leader 的状态同步以后恢复模式就结束了。状态同步保证了 leader 和 server 具有相同的系统状态。集群中为什么要有主节点在分布式环境中有些业务逻辑只需要集群中的某一台机器进行执行其他的机器可以共享这个结果这样可以大大减少重复计算提高性能所以就需要主节点。集群中有 3 台服务器其中一个节点宕机这个时候 zookeeper 还可以使用吗可以继续使用单数服务器只要没超过一半的服务器宕机就可以继续使用。说一下 zookeeper 的通知机制客户端会对某个 znode 建立一个 watcher 事件当该 znode 发生变化时这些客户端会收到 zookeeper 的通知然后客户端可以根据 znode 变化来做出业务上的改变。说一下 ACID 是什么Atomicity原子性一个事务transaction中的所有操作或者全部完成或者全部不完成不会结束在中间某个环节。事务在执行过程中发生错误会被恢复Rollback到事务开始前的状态就像这个事务从来没有执行过一样。即事务不可分割、不可约简。Consistency一致性在事务开始之前和事务结束以后数据库的完整性没有被破坏。Isolation隔离性数据库允许多个并发事务同时对其数据进行读写和修改的能力隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别包括读未提交Read uncommitted、读提交read committed、可重复读repeatable read和串行化Serializable。Durability持久性事务处理结束后对数据的修改就是永久的即便系统故障也不会丢失。mysql 的内连接、左连接、右连接有什么区别内连接是把匹配的关联数据显示出来左连接是左边的表全部显示出来右边的表显示出符合条件的数据右连接正好相反。mysql 索引是怎么实现的目前主流的数据库引擎的索引都是 B 树实现的B 树的搜索效率可以到达二分法的性能找到数据区域之后就找到了完整的数据结构了所有索引的性能也是更好的。怎么验证 mysql 的索引是否满足需求使用 explain 查看 SQL 是如何执行查询语句的从而分析你的索引是否满足需求。显示查询使用了哪一种类型从最好到最差依次是System const eq_ref ref range index ALL一般来说得保证查询到range级别最好能到ref级别。说一下 mysql 常用的引擎InnoDB 引擎InnoDB 引擎提供了对数据库 acid 事务的支持并且还提供了行级锁和外键的约束它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候InnoDB 会在内存中建立缓冲池用于缓冲数据和索引。但是该引擎是不支持全文搜索同时启动也比较的慢它是不会保存表的行数的所以当进行 select count() from table 指令的时候需要进行扫描全表。由于锁的粒度小写操作是不会锁定全表的,所以在并发度较高的场景下使用会提升效率的。MyIASM 引擎MySQL 的默认引擎但不提供事务的支持也不支持行级锁和外键。因此当执行插入和更新语句时即执行写操作的时候需要锁定这个表所以会导致效率会降低。不过和 InnoDB 不同的是MyIASM 引擎是保存了表的行数于是当进行 select count() from table 语句时可以直接的读取已经保存的值而不需要进行扫描全表。所以如果表的读操作远远多于写操作时并且不需要事务的支持的可以将 MyIASM 作为数据库引擎的首选。说一下 mysql 的行锁和表锁MyISAM 只支持表锁InnoDB 支持表锁和行锁默认为行锁。表级锁开销小加锁快不会出现死锁。锁定粒度大发生锁冲突的概率最高并发量最低。行级锁开销大加锁慢会出现死锁。锁力度小发生锁冲突的概率小并发度最高。说一下乐观锁和悲观锁乐观锁每次去拿数据的时候都认为别人不会修改所以不会上锁但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。悲观锁每次去拿数据的时候都认为别人会修改所以每次在拿数据的时候都会上锁这样别人想拿这个数据就会阻止直到这个锁被释放。数据库的乐观锁需要自己实现在表里面添加一个 version 字段每次修改成功值加 1这样每次修改的时候先对比一下自己拥有的 version 和数据库现在的 version 是否一致如果不一致就不修改这样就实现了乐观锁。如何做 mysql 的性能优化为搜索字段创建索引。避免使用 select *列出需要查询的字段。尽量把字段设置为NOT NULL。.不要在where条件中使用左右两边都是%的like模糊查询。尽量不要使用in 和not in会造成全表扫描。尽量不要使用or会造成全表扫描。尽量不要在 where 子句中对字段进行表达式操作这样也会造成全表扫描。redis 有哪些功能数据缓存功能分布式锁的功能支持数据持久化支持事务支持消息队列redis 为什么是单线程的避免了不必要的上下文切换和竞争条件也不存在多进程或者多线程导致的切换而消耗 CPU不用去考虑各种锁的问题不存在加锁释放锁操作没有因为可能出现死锁而导致的性能消耗。什么是缓存穿透、缓存击穿、缓存雪崩怎么解决缓存穿透key对应的数据在数据源并不存在每次针对此key的请求从缓存获取不到请求都会到数据源从而可能压垮数据源。解决方案采用布隆过滤器接口校验如果一个查询返回的数据为空仍然把这个空结果进行缓存但它的过期时间会很短最长不超过五分钟。缓存击穿key对应的数据存在但在redis中过期此时若有大量并发请求过来这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存这个时候大并发的请求可能会瞬间把后端DB压垮。一个key失效。解决方案根据key获取value值为空时锁上从数据库中load数据后再释放锁。缓存雪崩当缓存服务器重启或者大量缓存集中在某一个时间段失效这样在失效的时候也会给后端系统(比如DB)带来很大压力。多个key失效。解决方案可以给缓存的过期时间加上一个随机值时间使得每个 key 的过期时间分布开来不会集中在同一时刻失效。redis 支持的数据类型有哪些string、list、hash、set、zset。 怎么保证缓存和数据库数据的一致性合理设置缓存的过期时间。新增、更改、删除数据库操作时同步更新 Redis可以使用事物机制来保证数据的一致性。redis 持久化有几种方式RDB指定的时间间隔能对你的数据进行快照存储。AOF每一个收到的写命令都通过write函数追加到文件中。redis 怎么实现分布式锁一般使用 setnx指令只允许被一个程序占有使用完调用 del 释放锁。Redis的过期策略定时过期、惰性过期、定期过期。redis 淘汰策略有哪些volatile-lru从已设置过期时间的数据集server. db[i]. expires中挑选最近最少使用的数据淘汰。volatile-ttl从已设置过期时间的数据集server. db[i]. expires中挑选将要过期的数据淘汰。volatile-random从已设置过期时间的数据集server. db[i]. expires中任意选择数据淘汰。allkeys-lru从数据集server. db[i]. dict中挑选最近最少使用的数据淘汰。allkeys-random从数据集server. db[i]. dict中任意选择数据淘汰。no-enviction驱逐禁止驱逐数据。redis 常见的性能问题有哪些该如何解决主服务器写内存快照会阻塞主线程的工作当快照比较大时对性能影响是非常大的会间断性暂停服务所以主服务器最好不要写内存快照。Redis 主从复制的性能问题为了主从复制的速度和连接的稳定性主从库最好在同一个局域网内。 说一下 jvm 的主要组成部分及其作用类加载器运行时数据区执行引擎本地库接口组件的作用 首先通过类加载器会把 Java 代码转换成字节码运行时数据区再把字节码加载到内存中而字节码文件只是 JVM 的一套指令集规范并不能直接交给底层操作系统去执行因此需要特定的命令解析器执行引擎将字节码翻译成底层系统指令再交由 CPU 去执行而这个过程中需要调用其他语言的本地库接口来实现整个程序的功能。说一下 jvm 运行时数据区程序计数器虚拟机栈本地方法栈堆方法区说一下堆栈的区别栈内存存储的是局部变量而堆内存存储的是实体栈内存的更新速度要快于堆内存因为局部变量的生命周期很短栈内存存放的变量生命周期一旦结束就会被释放而堆内存存放的实体会被垃圾回收机制不定时的回收。什么是双亲委派模型如果一个类加载器收到了类加载的请求它首先不会自己去加载这个类而是把这个请求委派给父类加载器去完成每一层的类加载器都是如此这样所有的加载请求都会被传送到顶层的启动类加载器中只有当父加载无法完成加载请求它的搜索范围中没找到所需的类时子加载器才会尝试去加载类。说一下类加载的执行过程类加载分为以下 5 个步骤加载根据查找路径找到相应的 class 文件然后导入检查检查加载的 class 文件的正确性准备给类中的静态变量分配内存空间解析虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示而在直接引用直接指向内存中的地址初始化对静态变量和静态代码块执行初始化工作。怎么判断对象是否可以被回收引用计数器为每个对象创建一个引用计数有对象引用时计数器 1引用被释放时计数 -1当计数器为 0 时就可以被回收。它有一个缺点不能解决循环引用的问题可达性分析从 GC Roots 开始向下搜索搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时则证明此对象是可以被回收的。java 中都有哪些引用类型强引用软引用弱引用虚引用说一下 jvm 有哪些垃圾回收算法标记-清除算法标记-整理算法复制算法分代算法新生代垃圾回收器和老生代垃圾回收器都有哪些有什么区别新生代回收器Serial、ParNew、Parallel Scavenge老年代回收器Serial Old、Parallel Old、CMS整堆回收器G1新生代垃圾回收器一般采用的是复制算法复制算法的优点是效率高缺点是内存利用率低老年代回收器一般采用的是标记-整理的算法进行垃圾回收。 简述分代垃圾回收器是怎么工作的分代回收器有两个分区老生代和新生代新生代默认的空间占比总空间的 1/3老生代的默认占比是 2/3。新生代使用的是复制算法新生代里有 3 个分区Eden、To Survivor、From Survivor它们的默认占比是 8:1:1它的执行流程如下把 Eden  From Survivor 存活的对象放入 To Survivor 区清空 Eden 和 From Survivor 分区From Survivor 和 To Survivor 分区交换每次在 From Survivor 到 To Survivor 移动时都存活的对象年龄就 1当年龄到达 15默认配置是 15时升级为老生代。大对象也会直接进入老生代。老生代当空间占用到达某个值之后就会触发全局垃圾收回一般使用标记整理的执行算法。说一下 jvm 调优的工具JDK 自带了很多监控工具都位于 JDK 的 bin 目录下其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。jconsole用于对 JVM 中的内存、线程和类等进行监控jvisualvmJDK 自带的全能分析工具可以分析内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。常用的 jvm 调优的参数都有哪些-Xms2g初始化堆大小为 2g-Xmx2g堆最大内存为 2g-XX:NewRatio4设置年轻的和老年代的内存比例为 1:4-XX:SurvivorRatio8设置新生代 Eden 和 Survivor 比例为 8:2–XX:UseParNewGC指定使用 ParNew  Serial Old 垃圾回收器组合-XX:UseParallelOldGC指定使用 ParNew  ParNew Old 垃圾回收器组合-XX:UseConcMarkSweepGC指定使用 CMS  Serial Old 垃圾回收器组合-XX:PrintGC开启打印 gc 信息-XX:PrintGCDetails打印 gc 详细信息。spring中创建bean的三种方式通过默认无参构造方法创建使用静态工厂的方法创建对象使用实例工厂的方法创建对象Spring框架中Bean的创建过程实例化 - 属性赋值 - 初始化 - 销毁1. 实例化;2. 设置属性值;3. 如果实现了BeanNameAware接口,调用setBeanName设置Bean的ID或者Name;4. 如果实现BeanFactoryAware接口,调用setBeanFactory 设置BeanFactory;5. 如果实现ApplicationContextAware,调用setApplicationContext设置ApplicationContext6. 调用BeanPostProcessor的预先初始化方法;7. 调用InitializingBean的afterPropertiesSet()方法;8. 调用定制init-method方法9. 调用BeanPostProcessor的后初始化方法;10.对象销毁前调用destroy() 方法。我们要如何保证接口幂等性insert前先select加悲观锁加乐观锁加唯一索引建防重表根据状态机加分布式锁RocketMQ实现原理RocketMQ由NameServer注册中心集群、Producer生产者集群、Consumer消费者集群和若干BrokerRocketMQ进程组成。Broker在启动的时候去向所有的NameServer注册并保持长连接每30s发送一次心跳Producer在发送消息的时候从NameServer获取Broker服务器地址根据负载均衡算法选择一台服务器来发送消息Conusmer消费消息的时候同样从NameServer获取Broker地址然后主动拉取消息来消费。三大范式通俗解释第一范式1NF字段不可分第二范式2NF有主键非主键字段依赖主键第三范式3NF非主键字段不能相互依赖。RocketMQ消息零丢失方案总结生产者使用事务消息机制。Broker配置同步刷盘Dledger主从架构消费者不要使用异步消费。整个MQ挂了之后准备降级方案Spring传播行为REQUIRED默认值支持当前事务如果没有事务会创建一个新的事务SUPPORTS支持当前事务如果没有事务的话以非事务方式执行MANDATORY支持当前事务如果没有事务抛出异常REQUIRES_NEW创建一个新的事务并挂起当前事务NOT_SUPPORTED以非事务方式执行如果当前存在事务则将当前事务挂起NEVER以非事务方式进行如果存在事务则抛出异常NESTED如果当前存在事务则在嵌套事务内执行。如果当前没有事务则进行与REQUIRED类似的操作Spring 事务失效的场景未被Spring管理数据库引擎不支持事务事务方法没有被public修饰方法使用final修饰同一类中方法调用未开启事务多线程调用错误的传播行为自己try…catch…掉了异常手动抛出了错误的异常嵌套事务回滚多了Spring Boot启动流程1.首先从main找到run()方法在执行run()方法之前new一个SpringApplication对象2.进入run()方法创建应用监听器SpringApplicationRunListeners开始监听3.然后加载SpringBoot配置环境(ConfigurableEnvironment)然后把配置环境(Environment)加入监听对象中4.然后加载应用上下文(ConfigurableApplicationContext)5.最后创建Spring容器refreshContext(context)实现starter自动化配置和bean的实例化等工作。SpringBoot自动装配通过EnableAutoConfiguration注解在类路径的META-INF/spring.factories文件中找到所有的对应配置类然后将这些自动配置类加载到spring容器中。Nacos的高可用特性客户端重试一致性协议 distro本地缓存文件 Failover 机制心跳同步服务集群部署模式高可用Nacos的注册中心原理1.nocos客户端启动时会将当前服务的信息包含ip、端口号、服务名、集群名等信息封装为一个Instance对象然后创建一个定时任务每隔一段时间向Nacos服务器发送PUT请求并携带相关信息2.nacos服务器端在接收到心跳请求后会去检查当前服务列表中有没有该实例如果没有的话将当前服务实例重新注册注册完成后立即开启一个异步任务更新客户端实例的最后心跳时间如果当前实例是非健康状态则将其改为健康状态。3.当服务端检测到服务异常,基于UDP协议推送更新4.服务消费者即可调用了nacos配置中心原理配置动态刷新客户端有两种方式完成客户端主动Pull拉取配置Nacos Server主动Push配置数据Pull模式nacos采用了长轮询机制实现客户端发起一个Pull拉取配置请求nacos server建立一个任务队列返回配置数据给客户端Push模式当通过nacos dashboard或者nacos api修改了配置后nacos检查pull任务队列检查配置变更数据返回给Pull请求最新配置。ConcurrentHashMap工作原理底层数据结构Synchronized CAS Node 红黑树当执行put()操作1.先判断Node数组有没有初始化如果没有初始化先初始化initTable();2.根据key进行hash操作找到Node数组中的位置如果不存在hash冲突即该位置是null直接用CAS插入;3.如果存在hash冲突就先对链表的头节点或者红黑树的头节点加synchronized锁4.如果是链表就遍历链表如果key相同就执行覆盖操作如果不同就将元素插入到链表的尾部 并且在链表长度大于8 Node数组的长度超过64时会将链表的转化为红黑树。5.如果是红黑树就按照红黑树的结构进行插入。当执行get()操作get操作全程无锁。1.计算hash值定位到Node数组中的位置2.如果该位置为null则直接返回null3.如果该位置不为null再判断该节点是红黑树节点还是链表节点如果是红黑树节点使用红黑树的查找方式来进行查找如果是链表节点遍历链表进行查找线程池拒绝策略AbortPolicy丢弃任务并抛出 RejectedExecutionException 异常。默认这种DiscardPolicy丢弃任务但是不抛出异常DiscardOldestPolicy丢弃队列最前面的任务然后重新尝试执行任务重复此过程 。CallerRunsPolicy谁调用谁处理。由调用线程即提交任务给线程池的线程处理该任务如果线程池已经被shutdown则直接丢弃线程池的七个核心参数corePoolSize 线程池核心线程大小maximumPoolSize 线程池最大线程数量keepAliveTime 多余的空闲线程存活时间unit 空闲线程存活时间单位workQueue 工作队列threadFactory 线程工厂handler 拒绝策略Spring的启动原理第一步首先会执行一些容器刷新前的准备工作,如设置容器启动时间、一些状态标志位等第二步创建容器对象第三步准备Bean工厂第四步为上下文初始化 MessageSource即 国际化处理;第五步注册 Listener 监听器第六步实例化所有非懒加载的单实例 Bean第七步Spring容器完成刷新发布事件OOM(内存溢出)造成原因及解决方案内存泄漏;超大对象查看服务的进程是否存在;ps -ef | grep 服务名生产对堆快照Heap dump;jmap -dump:formatb,file/tmp/进程号_jmap_dump.hprof 进程号;分析生成的堆快照;