2023 亲自经历面试的初中级java面试题(持续更新)
面試題
- 基礎(chǔ)題
- 集合
- 說(shuō)一下list,set,map的區(qū)別。
- hashMap key是自己定義的類,有沒(méi)復(fù)寫過(guò)hashcode或者equals這些方法 ?
- 線程安全問(wèn)題
- List
- ArrayList 和 LinkedList 的區(qū)別是什么?
- Set
- HashSet的原理(怎么保證不重復(fù))?
- Map
- hashMap
- hashMap的原理(怎么存儲(chǔ)鍵值對(duì)的 /怎么put進(jìn)去的)
- HashMap和HashTable區(qū)別
- HashMap和HashSet的區(qū)別
- HashMap和TreeMap的區(qū)別
- TreeSet和HashSet區(qū)別
- 反射
- 什么是反射?
- 哪里用到反射機(jī)制?
- 線程
- 線程和進(jìn)程的區(qū)別?
- 守護(hù)線程是什么?
- 創(chuàng)建線程有哪幾種方式?
- 線程有哪些狀態(tài)?
- sleep() 和 wait() 有什么區(qū)別?
- 在 Java 程序中怎么保證多線程的運(yùn)行安全?
- 線程池
- 什么是線程池?
- 為什么要使用線程池?
- 線程池有什么作用?
- 線程池都有哪幾種工作隊(duì)列
- 鎖
- 悲觀鎖、樂(lè)觀鎖
- 什么是悲觀鎖,樂(lè)觀鎖
- 實(shí)現(xiàn)方式
- 什么是死鎖?
- synchronized 和 Lock 有什么區(qū)別?
- java垃圾回收
- GC的主要任務(wù)
- 垃圾回收機(jī)制的主要解決問(wèn)題
- 1、哪些內(nèi)存需要回收?如何判斷?
- 2、什么時(shí)候回收?
- 3、如何回收,這就牽扯到垃圾收集算法和垃圾收集器
- 垃圾回收總結(jié):
- JAVA8的新特性
- String類的常用方法有哪些?
- String,StringBuffer,StringBuilder的區(qū)別。
- GET 和POST 的區(qū)別?
- session與cookie的差別
- 說(shuō)一下 session 的工作原理?
- 如果客戶端禁止 cookie 能實(shí)現(xiàn) session 還能用嗎?
- 用戶登錄的功能服務(wù)器需要做什么,如何保持登錄狀態(tài)?
- 泛型是什么?
- 靜態(tài)屬性與普通屬性的區(qū)別是什么?
- throw 和 throws 的區(qū)別?
- final、finally、finalize 有什么區(qū)別?
- final
- finally
- finalize
- 說(shuō)一下堆棧的區(qū)別?
- 局部變量是存放在棧中,還是存放在堆棧中?
- 框架
- Spring
- Spring是什么?
- Spring有哪些優(yōu)點(diǎn)?
- AOP
- IOC
- 什么是 ORM 框架?
- 注解是怎么生效的?
- Spring事務(wù)的實(shí)現(xiàn)方式和實(shí)現(xiàn)原理
- Spring事務(wù)管理的方式有幾種?
- spring 中的 bean 是線程安全的嗎?
- spring 事務(wù)實(shí)現(xiàn)方式有哪些?
- 說(shuō)出Spring 或者 Springmvc中常用的5個(gè)注解,并解釋含義
- log4j日志級(jí)別
- SpringBoot
- SpringBoot是什么?
- Spring Boot 的配置文件有哪幾種格式?它們有什么區(qū)別?
- springboot事務(wù)是怎么去控制的 / 實(shí)現(xiàn)管理事務(wù)的?
- Spring Boot 的核心注解是哪個(gè)?它主要由哪幾個(gè)注解組成的?
- SpringBoot 常用注解
- Spring Boot 注冊(cè)bean的方法
- SpringBoot注入依賴及注解
- Spring Boot 自動(dòng)配置原理是什么?
- Springboot里面哪些注解屬于單例模式?
- @Controller和@RestController的區(qū)別
- springboot常用的starter有哪些?
- Mybatis
- Mybatis模糊查詢用#和$什么區(qū)別
- 簡(jiǎn)述Mybatis提供的兩級(jí)緩存,以及緩存的查找順序
- SpringCloud
- springCloud是什么?
- spring cloud 斷路器的作用是什么?
- spring cloud 的核心組件有哪些?
- 高并發(fā)
- 高并發(fā)解決方案案例
- 數(shù)據(jù)庫(kù)
- 索引
- 什么是索引?(為什么需要使用索引)
- 索引具體采用的哪種數(shù)據(jù)結(jié)構(gòu)
- 既然你提到InnoDB使用的B+ 樹(shù)的索引模型,那么你知道為什么采用B+ 樹(shù)嗎?這和Hash索引比較起來(lái)有什么優(yōu)缺點(diǎn)嗎?
- 優(yōu)化
- SQL語(yǔ)句優(yōu)化
- 分庫(kù)分表
- 讀寫分離
- Mysql和Oracle有什么區(qū)別?
- group by后面還可以加什么
- MySQL
- MySQL的事務(wù)
- 事務(wù)的并發(fā)問(wèn)題:
- MySQL事務(wù)隔離級(jí)別:
- 如何做 MySQL 的性能優(yōu)化?
- 怎么確定有沒(méi)有用到索引
- Redis
- Redis是什么及特點(diǎn)
- Redis除了緩存還能做什么
- Redis 有哪些功能?
- 一個(gè)字符串類型的值能存儲(chǔ)最大容量是多少?
- 最大能存多大?
- 線程安全嗎?
- redis 存儲(chǔ)結(jié)構(gòu)
- redis的基本數(shù)據(jù)類型
- 怎么理解Redis事務(wù)?
- 什么是Redis持久化?Redis有哪幾種持久化方式?優(yōu)缺點(diǎn)是什么?
- 什么情況下要用到緩存,什么數(shù)據(jù)適合緩存,使用緩存需要注意什么問(wèn)題?
- 什么是緩存擊穿?怎么解決?
- 什么是緩存穿透?怎么解決?
- 什么是緩存雪崩?怎么解決?
- 怎么保證緩存和數(shù)據(jù)庫(kù)數(shù)據(jù)的一致性?
- Redis悲觀鎖和樂(lè)觀鎖
- Redis 怎么實(shí)現(xiàn)分布式鎖?
- Redis 分布式鎖有什么缺陷?
- Redis 如何做內(nèi)存優(yōu)化?
- redis是單線程的,為什么那么快
- Redis 一級(jí)緩存與二級(jí)緩存(不知道答案對(duì)不對(duì))
- Nginx
- 請(qǐng)解釋一下什么是Nginx?
- 請(qǐng)列舉Nginx和Apache 之間的不同點(diǎn)
- 請(qǐng)解釋Nginx如何處理HTTP請(qǐng)求
- 請(qǐng)列舉Nginx的一些特性
- 簡(jiǎn)述反向代理和正向代理
- 正向代理:
- 反向代理:
- 使用“反向代理服務(wù)器”的優(yōu)點(diǎn)是什么?
- nginx負(fù)載均衡的幾種常用方式
- 解決nginx負(fù)載均衡的session共享問(wèn)題
- 一些配置
- 安全性
- 攻擊
- 注入攻擊
- 如何避免 SQL 注入?
- 什么是 XSS 攻擊,如何避免?
- 設(shè)計(jì)模式
- 說(shuō)一下你熟悉的設(shè)計(jì)模式?
- 單例模式
- 工廠模式
- 觀察者模式
- 外觀模式
- 模版方法模式
- tomcat
- 默認(rèn)線程數(shù)
- Shiro
- 談?wù)凷hiro的工作流程
- 權(quán)限的注解
- Linux
- 拷文件
- 跳節(jié)點(diǎn)
- 前端
- 前端跨域怎么實(shí)現(xiàn)
- vue2生命周期
- vue3生命周期
基礎(chǔ)題
集合
說(shuō)一下list,set,map的區(qū)別。
List:
1.可以允許重復(fù)的對(duì)象。
2.可以插入多個(gè)null元素。
3.是一個(gè)有序容器,保持了每個(gè)元素的插入順序,輸出的順序就是插入的順序。
4.常用的實(shí)現(xiàn)類有 ArrayList、LinkedList 和 Vector。ArrayList 最為流行,它提供了使用索引的隨意訪問(wèn),而 LinkedList 則對(duì)于經(jīng)常需要從 List 中添加或刪除元素的場(chǎng)合更為合適。
Set:
1.不允許重復(fù)對(duì)象
2. 無(wú)序容器,你無(wú)法保證每個(gè)元素的存儲(chǔ)順序,TreeSet通過(guò) Comparator 或者 Comparable 維護(hù)了一個(gè)排序順序。
3. 只允許一個(gè) null 元素
4.Set 接口最流行的幾個(gè)實(shí)現(xiàn)類是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 實(shí)現(xiàn)的 HashSet;TreeSet 還實(shí)現(xiàn)了 SortedSet 接口,因此 TreeSet 是一個(gè)根據(jù)其
compare() 和 compareTo() 的定義進(jìn)行排序的有序容器。
Map:
1.Map不是collection的子接口或者實(shí)現(xiàn)類。Map是一個(gè)接口。
2.Map 的 每個(gè) Entry 都持有兩個(gè)對(duì)象,也就是一個(gè)鍵一個(gè)值,Map 可能會(huì)持有相同的值對(duì)象但鍵對(duì)象必須是唯一的。
3. TreeMap 也通過(guò) Comparator 或者 Comparable 維護(hù)了一個(gè)排序順序。
4. Map 里你可以擁有隨意個(gè) null 值但最多只能有一個(gè) null 鍵。
5.Map 接口最流行的幾個(gè)實(shí)現(xiàn)類是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)
hashMap key是自己定義的類,有沒(méi)復(fù)寫過(guò)hashcode或者equals這些方法 ?
線程安全問(wèn)題
ArrayList、LinkedList、HashSet、HashMap是非線程安全的
HashTable,Vector是線程安全的;
StringBuilder是非線程安全的,StringBuffer是線程安全的。
List
ArrayList
優(yōu)點(diǎn): 底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快,增刪慢。
缺點(diǎn): 線程不安全,效率高
LinkedList
優(yōu)點(diǎn): 底層數(shù)據(jù)結(jié)構(gòu)是鏈表,查詢慢,增刪快。
缺點(diǎn): 線程不安全,效率高
Vector
優(yōu)點(diǎn): 底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快,增刪慢。
缺點(diǎn): 線程安全,效率低
ArrayList 和 LinkedList 的區(qū)別是什么?
數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn):ArrayList 是動(dòng)態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn),而 LinkedList 是雙向鏈表的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。
隨機(jī)訪問(wèn)效率:對(duì)于隨機(jī)訪問(wèn)get和set,ArrayList覺(jué)得優(yōu)于LinkedList,因?yàn)?LinkedList 是線性的數(shù)據(jù)存儲(chǔ)方式,所以需要移動(dòng)指針從前往后依次查找。
增加和刪除效率:對(duì)于新增和刪除操作add和remove,LinkedList比較占優(yōu)勢(shì),因?yàn)锳rrayList要移動(dòng)數(shù)據(jù)。 這一點(diǎn)要看實(shí)際情況的。若只對(duì)單條數(shù)據(jù)插入或刪除,ArrayList的速度反而優(yōu)于LinkedList。但若是批量隨機(jī)的插入刪除數(shù)據(jù),LinkedList的速度大大優(yōu)于ArrayList. 因?yàn)锳rrayList每插入一條數(shù)據(jù),要移動(dòng)插入點(diǎn)及之后的所有數(shù)據(jù)。。
綜合來(lái)說(shuō),在需要頻繁讀取集合中的元素時(shí),更推薦使用 ArrayList,而在插入和刪除操作較多時(shí),更推薦使用 LinkedList。
Set
HashSet
底層數(shù)據(jù)結(jié)構(gòu)是哈希表。(無(wú)序,唯一)
如何來(lái)保證元素唯一性?
1.依賴兩個(gè)方法:hashCode()和equals()
LinkedHashSet
底層數(shù)據(jù)結(jié)構(gòu)是鏈表和哈希表。(FIFO插入有序,唯一)
1.由鏈表保證元素有序
2.由哈希表保證元素唯一
TreeSet
底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹(shù)。(唯一,有序)
HashSet的原理(怎么保證不重復(fù))?
HashSet保證元素不重復(fù)是通過(guò)兩部分實(shí)現(xiàn)的,第一步通過(guò)比較兩個(gè)對(duì)象的哈希碼是否相同如果相同,只能懷疑是相同對(duì)象,那么進(jìn)而就會(huì)調(diào)用equals就行二次確認(rèn),如果確認(rèn)完畢之后相同,那么就會(huì)排除第二個(gè),否則的話就會(huì)插入該元素。因此,如果要保證存入對(duì)象的內(nèi)容不同的時(shí)候就需要同時(shí)重寫hash()和equals()方法自己定義比較的規(guī)則,一定要保證相同內(nèi)容的對(duì)象的哈希碼是相同的,不同對(duì)象的哈希碼是不同的。
Map
Map接口有三個(gè)比較重要的實(shí)現(xiàn)類,分別是HashMap、TreeMap和HashTable。
TreeMap是有序的,HashMap和HashTable是無(wú)序的。
Hashtable是線程安全的,HashMap不是線程安全的。
HashMap效率較高,Hashtable效率較低。
如果對(duì)同步性或與遺留代碼的兼容性沒(méi)有任何要求,建議使用HashMap。 查看
Hashtable的源代碼 就可以發(fā)現(xiàn),除構(gòu)造函數(shù)外,Hashtable的所有 public 方
法聲明中都有 synchronized關(guān)鍵字,而HashMap的源碼中則沒(méi)有。
Hashtable不允許null值,HashMap允許null值(key和value都允許)
父類不同:Hashtable的父類是Dictionary,HashMap的父類是AbstractMap
hashMap
hashMap比較好的一些問(wèn)題https://www.cnblogs.com/heqiyoujing/p/11143298.html
hashMap的原理(怎么存儲(chǔ)鍵值對(duì)的 /怎么put進(jìn)去的)
第一種(簡(jiǎn)單):
HashMap 基于 Hash 算法實(shí)現(xiàn)的,我們通過(guò) put(key,value)存儲(chǔ),get(key)來(lái)獲取。當(dāng)傳入 key 時(shí),HashMap 會(huì)根據(jù) key. hashCode() 計(jì)算出 hash 值,根據(jù) hash 值將 value 保存在 bucket 里。下一次key傳入時(shí),同樣計(jì)算hash值,并用equals比較。當(dāng)計(jì)算出的 hash 值相同時(shí),我們稱之為 hash 沖突,HashMap 的做法是用鏈表和紅黑樹(shù)存儲(chǔ)相同 hash 值的 value。當(dāng) hash 沖突的個(gè)數(shù)比較少時(shí)使用鏈表,否則使用紅黑樹(shù)。
第二種(這種聽(tīng)著比較牛):
調(diào)用哈希函數(shù)獲取Key對(duì)應(yīng)的hash值,再計(jì)算其數(shù)組下標(biāo);
如果沒(méi)有出現(xiàn)哈希沖突,則直接放入數(shù)組;如果出現(xiàn)哈希沖突,則以鏈表的方式放在鏈表后面;
如果鏈表長(zhǎng)度超過(guò)閥值( TREEIFY THRESHOLD==8),就把鏈表轉(zhuǎn)成紅黑樹(shù),鏈表長(zhǎng)度低于6,就把紅黑樹(shù)轉(zhuǎn)回鏈表;
如果結(jié)點(diǎn)的key已經(jīng)存在,則替換其value即可;
如果集合中的鍵值對(duì)大于12,調(diào)用resize方法進(jìn)行數(shù)組擴(kuò)容。”
HashMap和HashTable區(qū)別
(1)線程安全性不同
HashMap是線程不安全的,HashTable是線程安全的,其中的方法是Synchronize的,在多線程并發(fā)的情況下,可以直接使用HashTable,但是使用HashMap時(shí)必須自己增加同步處理。
(2)是否提供contains方法
HashMap只有containsValue和containsKey方法;HashTable有contains、containsKey和containsValue三個(gè)方法,其中contains和containsValue方法功能相同。
(3)key和value是否允許null值
Hashtable中,key和value都不允許出現(xiàn)null值。HashMap中,null可以作為鍵,這樣的鍵只有一個(gè);可以有一個(gè)或多個(gè)鍵所對(duì)應(yīng)的值為null。
(4)數(shù)組初始化和擴(kuò)容機(jī)制
HashTable在不指定容量的情況下的默認(rèn)容量為11,而HashMap為16,Hashtable不要求底層數(shù)組的容量一定要為2的整數(shù)次冪,而HashMap則要求一定為2的整數(shù)次冪。
Hashtable擴(kuò)容時(shí),將容量變?yōu)樵瓉?lái)的2倍加1,而HashMap擴(kuò)容時(shí),將容量變?yōu)樵瓉?lái)的2倍。
HashMap和HashSet的區(qū)別
HashMap和TreeMap的區(qū)別
HashMap:數(shù)組方式存儲(chǔ)key/value,線程非安全,允許null作為key和value,key不可以重復(fù),value允許重復(fù),不保證元素迭代順序是按照插入時(shí)的順序,key的hash值是先計(jì)算key的hashcode值,然后再進(jìn)行計(jì)算,每次容量擴(kuò)容會(huì)重新計(jì)算所以key的hash值,會(huì)消耗資源,要求key必須重寫equals和hashcode方法
TreeMap:基于紅黑二叉樹(shù)的NavigableMap的實(shí)現(xiàn),線程非安全,不允許null,key不可以重復(fù),value允許重復(fù),存入TreeMap的元素應(yīng)當(dāng)實(shí)現(xiàn)Comparable接口或者實(shí)現(xiàn)Comparator接口,會(huì)按照排序后的順序迭代元素,兩個(gè)相比較的key不得拋出classCastException。主要用于存入元素的時(shí)候?qū)υ剡M(jìn)行自動(dòng)排序,迭代輸出的時(shí)候就按排序順序輸出
TreeSet和HashSet區(qū)別
HashSet是采用hash表來(lái)實(shí)現(xiàn)的。其中的元素沒(méi)有按順序排列,add()、remove()以及contains()等方法都是復(fù)雜度為O(1)的方法。
TreeSet是采用樹(shù)結(jié)構(gòu)實(shí)現(xiàn)(紅黑樹(shù)算法)。元素是按順序進(jìn)行排列,但是add()、remove()以及contains()等方法都是復(fù)雜度為O(log (n))的方法。它還提供了一些方法來(lái)處理排序的set,如first(), last(), headSet(), tailSet()等等。
反射
什么是反射?
反射就是程序運(yùn)行期間jvm會(huì)洞悉任意一個(gè)類的屬性和方法,對(duì)任意一個(gè)對(duì)象都能夠訪問(wèn)它的屬性和方法。依靠此機(jī)制,可以動(dòng)態(tài)的創(chuàng)建一個(gè)類的對(duì)象和調(diào)用對(duì)象的方法
優(yōu)點(diǎn):增加靈活性,可以在運(yùn)行時(shí)動(dòng)態(tài)獲取對(duì)象
缺點(diǎn):效率低,破壞封裝,通過(guò)發(fā)射可以訪問(wèn)類的私有方法,不安全
哪里用到反射機(jī)制?
1.JDBC中,利用反射動(dòng)態(tài)加載了數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序。
2.Web服務(wù)器中利用反射調(diào)用了Sevlet的服務(wù)方法。
3.Eclispe等開(kāi)發(fā)工具利用反射動(dòng)態(tài)刨析對(duì)象的類型與結(jié)構(gòu),動(dòng)態(tài)提示對(duì)象的屬性和方法。
4.很多框架都用到反射機(jī)制,注入屬性,調(diào)用方法,如Spring。
線程
線程和進(jìn)程的區(qū)別?
一個(gè)程序下至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程下至少有一個(gè)線程,一個(gè)進(jìn)程下也可以有多個(gè)線程來(lái)增加程序的執(zhí)行速度。
守護(hù)線程是什么?
守護(hù)線程是運(yùn)行在后臺(tái)的一種特殊線程。它獨(dú)立于控制終端并且周期性地執(zhí)行某種任務(wù)或等待處理某些發(fā)生的事件。在 Java 中垃圾回收線程就是特殊的守護(hù)線程。
創(chuàng)建線程有哪幾種方式?
繼承 Thread 重新 run 方法;
實(shí)現(xiàn) Runnable 接口;
實(shí)現(xiàn) Callable 接口。
線程有哪些狀態(tài)?
NEW 尚未啟動(dòng)
RUNNABLE 正在執(zhí)行中
BLOCKED 阻塞的(被同步鎖或者IO鎖阻塞)
WAITING 永久等待狀態(tài)
TIMED_WAITING 等待指定的時(shí)間重新被喚醒的狀態(tài)
TERMINATED 執(zhí)行完成
sleep() 和 wait() 有什么區(qū)別?
類的不同:sleep() 來(lái)自 Thread,wait() 來(lái)自 Object。
釋放鎖:sleep() 不釋放鎖;wait() 釋放鎖。
用法不同:sleep() 時(shí)間到會(huì)自動(dòng)恢復(fù);wait() 可以使用 notify()/notifyAll()直接喚醒。
在 Java 程序中怎么保證多線程的運(yùn)行安全?
方法一:使用安全類,比如 Java. util. concurrent 下的類。比如:ConCurrentHashMap
方法二:使用自動(dòng)鎖 synchronized。
方法三:使用手動(dòng)鎖 Lock。
線程池
什么是線程池?
線程池就是事先將線程放到一個(gè)容器中,當(dāng)使用線程的時(shí)候,不用再去new出一個(gè)線程,直接從線程池取出來(lái)就可以了
為什么要使用線程池?
創(chuàng)建線程和銷毀線程的花銷是比較大的,這些時(shí)間有可能比處理業(yè)務(wù)的時(shí)間還要長(zhǎng)。這樣頻繁的創(chuàng)建線程和銷毀線程,再加上業(yè)務(wù)工作線程,消耗系統(tǒng)資源的時(shí)間,可能導(dǎo)致系統(tǒng)資源不足。(我們可以把創(chuàng)建和銷毀的線程的過(guò)程去掉)
線程池有什么作用?
1、提高效率 創(chuàng)建好一定數(shù)量的線程放在池中,等需要使用的時(shí)候就從池中拿一個(gè),這要比需要的時(shí)候創(chuàng)建一個(gè)線程對(duì)象要快的多。
2、方便管理 可以編寫線程池管理代碼對(duì)池中的線程同一進(jìn)行管理,比如說(shuō)啟動(dòng)時(shí)有該程序創(chuàng)建100個(gè)線程,每當(dāng)有請(qǐng)求的時(shí)候,就分配一個(gè)線程去工作,如果剛好并發(fā)有101個(gè)請(qǐng)求,那多出的這一個(gè)請(qǐng)求可以排隊(duì)等候,避免因無(wú)休止的創(chuàng)建線程導(dǎo)致系統(tǒng)崩潰。
線程池都有哪幾種工作隊(duì)列
1、ArrayBlockingQueue
是一個(gè)基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列,此隊(duì)列按 FIFO(先進(jìn)先出)原則對(duì)元素進(jìn)行排序。
2、LinkedBlockingQueue
一個(gè)基于鏈表結(jié)構(gòu)的阻塞隊(duì)列,此隊(duì)列按FIFO (先進(jìn)先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。靜態(tài)工廠方法Executors.newFixedThreadPool()使用了這個(gè)隊(duì)列
3、SynchronousQueue
一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列。每個(gè)插入操作必須等到另一個(gè)線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài),吞吐量通常要高于LinkedBlockingQueue,靜態(tài)工廠方法Executors.newCachedThreadPool使用了這個(gè)隊(duì)列。
4、PriorityBlockingQueue
一個(gè)具有優(yōu)先級(jí)的無(wú)限阻塞隊(duì)列
鎖
悲觀鎖、樂(lè)觀鎖
什么是悲觀鎖,樂(lè)觀鎖
樂(lè)觀鎖和悲觀鎖是兩種思想,用于解決并發(fā)場(chǎng)景下的數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題。
樂(lè)觀鎖:樂(lè)觀鎖在操作數(shù)據(jù)時(shí)非常樂(lè)觀,認(rèn)為別人不會(huì)同時(shí)修改數(shù)據(jù)。因此樂(lè)觀鎖不會(huì)上鎖,只是在執(zhí)行更新的時(shí)候判斷一下在此期間別人是否修改了數(shù)據(jù):如果別人修改了數(shù)據(jù)則放棄操作,否則執(zhí)行操作。
悲觀鎖:悲觀鎖在操作數(shù)據(jù)時(shí)比較悲觀,認(rèn)為別人會(huì)同時(shí)修改數(shù)據(jù)。因此操作數(shù)據(jù)時(shí)直接把數(shù)據(jù)鎖住,直到操作完成后才會(huì)釋放鎖;上鎖期間其他人不能修改數(shù)據(jù)。
實(shí)現(xiàn)方式
悲觀鎖的實(shí)現(xiàn)方式是加鎖,加鎖既可以是對(duì)代碼塊加鎖(如Java的synchronized關(guān)鍵字),也可以是對(duì)數(shù)據(jù)加鎖(如MySQL中的排它鎖)。
樂(lè)觀鎖的實(shí)現(xiàn)方式:
CAS(Compare and Swap)比較并交換,是一種樂(lè)觀鎖的實(shí)現(xiàn),是用非阻塞算法來(lái)代替鎖定,其中 java.util.concurrent 包下的 AtomicInteger 就是借助 CAS 來(lái)實(shí)現(xiàn)的。
但 CAS 也不是沒(méi)有任何副作用,比如著名的 ABA 問(wèn)題就是 CAS 引起的。
什么是死鎖?
當(dāng)線程 A 持有獨(dú)占鎖a,并嘗試去獲取獨(dú)占鎖 b 的同時(shí),線程 B 持有獨(dú)占鎖 b,并嘗試獲取獨(dú)占鎖 a 的情況下,就會(huì)發(fā)生 AB 兩個(gè)線程由于互相持有對(duì)方需要的鎖,而發(fā)生的阻塞現(xiàn)象,我們稱為死鎖。
避免死鎖最簡(jiǎn)單的方法就是阻塞循環(huán)等待條件,將系統(tǒng)中所有資源設(shè)置標(biāo)志位、排序,規(guī)定所有的進(jìn)程申請(qǐng)資源必須以一定的順序(升序或者降序)做操作來(lái)避免死鎖
synchronized 和 Lock 有什么區(qū)別?
54.synchronized 可以給類、方法、代碼塊加鎖;而 lock 只能給代碼塊加鎖。
synchronized 不需要手動(dòng)獲取鎖和釋放鎖,使用簡(jiǎn)單,發(fā)生異常會(huì)自動(dòng)釋放鎖,不會(huì)造成死鎖;而 lock 需要自己加鎖和釋放鎖,如果使用不當(dāng)沒(méi)有 unLock()去釋放鎖就會(huì)造成死鎖。
通過(guò) Lock 可以知道有沒(méi)有成功獲取鎖,而 synchronized 卻無(wú)法辦到。
java垃圾回收
GC的主要任務(wù)
1.分配內(nèi)存
2.確保被引用對(duì)象的內(nèi)存不被錯(cuò)誤的回收
3.回收不再被引用的對(duì)象的內(nèi)存空間
垃圾回收機(jī)制的主要解決問(wèn)題
1、哪些內(nèi)存需要回收?如何判斷?
垃圾收集器會(huì)對(duì)堆進(jìn)行回收前,確定對(duì)象中哪些是“存活”,哪些是“死亡”(不可能再被任何途徑使用的對(duì)象)
判斷方法:
1、引用計(jì)數(shù)算法(不推薦)
每當(dāng)一個(gè)地方引用它時(shí),計(jì)數(shù)器+1;引用失效時(shí),計(jì)數(shù)器-1;計(jì)數(shù)值=0——不可能再被引用。
查看運(yùn)行結(jié)果,會(huì)發(fā)現(xiàn)并沒(méi)有因?yàn)閮蓚€(gè)對(duì)象互相引用就沒(méi)有回收,因此引用計(jì)數(shù)算法很難解決對(duì)象之間相互矛盾循環(huán)引用的問(wèn)題
2、可達(dá)性分析算法(推薦)
當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連,即不可達(dá)時(shí),則證明此對(duì)象時(shí)不可用的。
舉例:一顆樹(shù)有很多丫枝,其中一個(gè)分支斷了,跟樹(shù)上沒(méi)有任何聯(lián)系,那就說(shuō)明這個(gè)分支沒(méi)有用了,就可以當(dāng)垃圾回收去燒了。
2、什么時(shí)候回收?
1、會(huì)在cpu空閑的時(shí)候自動(dòng)進(jìn)行回收
2、在堆內(nèi)存存儲(chǔ)滿了之后
3、主動(dòng)調(diào)用System.gc()后嘗試進(jìn)行回收
3、如何回收,這就牽扯到垃圾收集算法和垃圾收集器
1)標(biāo)記—清除算法
這是最基礎(chǔ)的一種算法,分為兩個(gè)步驟,第一個(gè)步驟就是標(biāo)記,也就是標(biāo)記處所有需要回收的對(duì)象,標(biāo)記完成后就進(jìn)行統(tǒng)一的回收掉哪些帶有標(biāo)記的對(duì)象。這種算法優(yōu)點(diǎn)是簡(jiǎn)單,缺點(diǎn)是效率問(wèn)題,還有一個(gè)最大的缺點(diǎn)是空間問(wèn)題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,當(dāng)程序在以后的運(yùn)行過(guò)程中需要分配較大對(duì)象時(shí)無(wú)法找到足夠的連續(xù)內(nèi)存而造成內(nèi)存空間浪費(fèi)。
兩個(gè)階段:標(biāo)記,清除;
不足:效率問(wèn)題;空間問(wèn)題(會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片)
2)復(fù)制算法
復(fù)制將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過(guò)的內(nèi)存空間一次清理掉。這樣使得每次都是對(duì)其中的一塊進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況。只是這種算法的代價(jià)是將內(nèi)存縮小為原來(lái)的一半。
不足:將內(nèi)存縮小為了原來(lái)的一半
3)標(biāo)記—整理算法
標(biāo)記整理算法與標(biāo)記清除算法很相似,但最顯著的區(qū)別是:標(biāo)記清除算法僅對(duì)不存活的對(duì)象進(jìn)行處理,剩余存活對(duì)象不做任何處理,造成內(nèi)存碎片;而標(biāo)記整理算法不僅對(duì)不存活對(duì)象進(jìn)行處理清除,還對(duì)剩余的存活對(duì)象進(jìn)行整理,重新整理,因此其不會(huì)產(chǎn)生內(nèi)存碎片。
兩個(gè)階段:標(biāo)記,清除;
(讓存活的對(duì)象都向一端移動(dòng)
3)分代收集算法
分代收集算法是一種比較智能的算法,也是現(xiàn)在jvm使用最多的一種算法,他本身其實(shí)不是一個(gè)新的算法,而是他會(huì)在具體的場(chǎng)景自動(dòng)選擇以上三種算法進(jìn)行垃圾對(duì)象回收。
那么現(xiàn)在的重點(diǎn)就是分代收集算法中說(shuō)的自動(dòng)根據(jù)具體場(chǎng)景進(jìn)行選擇。這個(gè)具體場(chǎng)景到底是什么場(chǎng)景。
場(chǎng)景其實(shí)指的是針對(duì)jvm的哪一個(gè)區(qū)域,1.7之前jvm把內(nèi)存分為三個(gè)區(qū)域:新生代,老年代,永久代
JVM會(huì)將堆內(nèi)存分為兩個(gè)區(qū)域,一個(gè)新生代,一個(gè)老年代。
新生代:就是創(chuàng)建和使用完之后立馬就要被回收的對(duì)象放在里面
老年代:把一些會(huì)長(zhǎng)期存活的對(duì)象放在里面。
永久代:用于存放一些靜態(tài)文件,如Java類、方法等
了解過(guò)場(chǎng)景之后再結(jié)合分代收集算法得出結(jié)論:
1、在新生代中,每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活,那就選用復(fù)制算法。只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集。
2、老年代中因?yàn)閷?duì)象存活率高、沒(méi)有額外空間對(duì)他進(jìn)行分配擔(dān)保,就必須用標(biāo)記-清除或者標(biāo)記-整理。
垃圾回收總結(jié):
JAVA8的新特性
Lambda 表達(dá)式 ? Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞到方法中)。
方法引用 ? 方法引用提供了非常有用的語(yǔ)法,可以直接引用已有Java類或?qū)ο?#xff08;實(shí)例)的方法或構(gòu)造器。與lambda聯(lián)合使用,方法引用可以使語(yǔ)言的構(gòu)造更緊湊簡(jiǎn)潔,減少冗余代碼。
默認(rèn)方法 ? 默認(rèn)方法就是一個(gè)在接口里面有了一個(gè)實(shí)現(xiàn)的方法。
新工具 ? 新的編譯工具,如:Nashorn引擎 jjs、 類依賴分析器jdeps。
Stream API ?新添加的Stream API(java.util.stream) 把真正的函數(shù)式編程風(fēng)格引入到Java中。
Date Time API ? 加強(qiáng)對(duì)日期與時(shí)間的處理。
Optional 類 ? Optional 類已經(jīng)成為 Java 8 類庫(kù)的一部分,用來(lái)解決空指針異常。
Nashorn, JavaScript 引擎 ? Java 8提供了一個(gè)新的Nashorn javascript引擎,它允許我們?cè)贘VM上運(yùn)行特定的javascript應(yīng)用。
String類的常用方法有哪些?
答:https://zhidao.baidu.com/question/232452768.html
String,StringBuffer,StringBuilder的區(qū)別。
第一種回答
答:1)如果操作少量的數(shù)據(jù)用String(查看源碼得知,String類的聲明是:public
final,改變它的值相當(dāng)于創(chuàng)建一個(gè)新的字符串)
2)單線程下操作大量的數(shù)據(jù)用StringBuilder
3)多線程下操作大量的數(shù)據(jù)用StringBuffer
https://www.cnblogs.com/A_ming/archive/2010/04/13/1711395.html
第二種回答
(1)StringBuffer 與 StringBuilder 中的方法和功能完全是等價(jià)的,
(2)只是StringBuffer 中的方法大都采用了 synchronized 關(guān)鍵字進(jìn)行修飾,因此是線程安全的,而 StringBuilder 沒(méi)有這個(gè)修飾,可以被認(rèn)為是線程不安全的。
(3)在單線程程序下,StringBuilder效率更快,因?yàn)樗恍枰渔i,不具備多線程安全而StringBuffer則每次都需要判斷鎖,效率相對(duì)更低
GET 和POST 的區(qū)別?
GET 請(qǐng)求的數(shù)據(jù)會(huì)附在URL 之后(就是把數(shù)據(jù)放置在 HTTP 協(xié)議頭中),以?分割URL 和傳輸數(shù)據(jù),參數(shù)之間以&相連,如:login.action?name=zhagnsan&password=123456。POST 把提交的數(shù)據(jù)則放置在是 HTTP 包的包體中。
session與cookie的差別
Cookie實(shí)際上是一小段的文本信息。客戶端請(qǐng)求服務(wù)器,如果服務(wù)器需要記錄該用戶狀態(tài),就使用response向客戶端瀏覽器頒發(fā)一個(gè)Cookie。客戶端瀏覽器會(huì)把Cookie保存起來(lái)。當(dāng)瀏覽器再請(qǐng)求該網(wǎng)站時(shí),瀏覽器把請(qǐng)求的網(wǎng)址連同該Cookie一同提交給服務(wù)器。服務(wù)器檢查該Cookie,以此來(lái)辨認(rèn)用戶狀態(tài)。服務(wù)器還可以根據(jù)需要修改Cookie的內(nèi)容。
Session 是存儲(chǔ)在 web 服務(wù)器端的一塊信息。session 對(duì)象存儲(chǔ)特定用戶會(huì)話所需的屬性及配置信息。當(dāng)用戶在應(yīng)用程序的 Web 頁(yè)之間跳轉(zhuǎn)時(shí),存儲(chǔ)在 Session 對(duì)象中的變量將不會(huì)丟失,而是在整個(gè)用戶會(huì)話中一直存在下去。
Cookie 和session 的不同點(diǎn):
(1)無(wú)論客戶端做怎樣的設(shè)置,session 都能夠正常工作。當(dāng)客戶端禁用 cookie 時(shí)將無(wú)法使用 cookie。
(2)在存儲(chǔ)的數(shù)據(jù)量方面:session 能夠存儲(chǔ)任意的java 對(duì)象,cookie 只能存儲(chǔ) String 類型的對(duì)象。
(3)cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上
說(shuō)一下 session 的工作原理?
session 的工作原理是客戶端登錄完成之后,服務(wù)器會(huì)創(chuàng)建對(duì)應(yīng)的 session,session 創(chuàng)建完之后,會(huì)把 session 的 id 發(fā)送給客戶端,客戶端再存儲(chǔ)到瀏覽器中。這樣客戶端每次訪問(wèn)服務(wù)器時(shí),都會(huì)帶著 sessionid,服務(wù)器拿到 sessionid 之后,在內(nèi)存找到與之對(duì)應(yīng)的 session 這樣就可以正常工作了。
如果客戶端禁止 cookie 能實(shí)現(xiàn) session 還能用嗎?
可以用
一般默認(rèn)情況下,在會(huì)話中,服務(wù)器存儲(chǔ) session 的 sessionid 是通過(guò) cookie 存到瀏覽器里。
如果瀏覽器禁用了 cookie,瀏覽器請(qǐng)求服務(wù)器無(wú)法攜帶 sessionid,服務(wù)器無(wú)法識(shí)別請(qǐng)求中的用戶身份,session失效。
但是可以通過(guò)其他方法在禁用 cookie 的情況下,可以繼續(xù)使用session。
1、通過(guò)url重寫,把 sessionid 作為參數(shù)追加的原 url 中,后續(xù)的瀏覽器與服務(wù)器交互中攜帶 sessionid 參數(shù)。
2、服務(wù)器的返回?cái)?shù)據(jù)中包含 sessionid,瀏覽器發(fā)送請(qǐng)求時(shí),攜帶 sessionid 參數(shù)。
3、通過(guò) Http 協(xié)議其他 header 字段,服務(wù)器每次返回時(shí)設(shè)置該 header 字段信息,瀏覽器中 js 讀取該 header 字段,請(qǐng)求服務(wù)器時(shí),js設(shè)置攜帶該 header 字段。
用戶登錄的功能服務(wù)器需要做什么,如何保持登錄狀態(tài)?
第一種,cookie和session的配合使用
實(shí)現(xiàn)原理:當(dāng)用戶請(qǐng)求頁(yè)面,一般需要先登錄,用戶第一次輸入用戶名和密碼之后,前臺(tái)發(fā)送post請(qǐng)求,后臺(tái)獲取用戶信息,通過(guò)查詢數(shù)據(jù)庫(kù)來(lái)驗(yàn)證用戶信息是否正確,如果驗(yàn)證通過(guò),則會(huì)開(kāi)辟一塊session空間來(lái)儲(chǔ)存用戶數(shù)據(jù),并且同時(shí)生成一個(gè)cookie字符串,由后臺(tái)返回給前臺(tái),前臺(tái)接收后,會(huì)把這個(gè)cookie字符串儲(chǔ)存到瀏覽器的cookie空間中,這個(gè)cookie就相當(dāng)于一把鑰匙,可以打開(kāi)后臺(tái)存儲(chǔ)對(duì)應(yīng)用戶信息的鎖,當(dāng)用戶下一次請(qǐng)求的時(shí)候,客戶端便會(huì)自動(dòng)攜帶這個(gè)cookie去請(qǐng)求服務(wù)器,服務(wù)器識(shí)別后,就會(huì)讀取session中的用戶信息,這樣用戶就可以直接訪問(wèn),就不需要再輸入用戶名密碼來(lái)驗(yàn)證身份了。
優(yōu)缺點(diǎn):
優(yōu)點(diǎn)是:提升了用戶體驗(yàn),cookie和session的結(jié)合使用,比直接在客戶端保存用戶信息要相對(duì)安全;缺點(diǎn)是:當(dāng)服務(wù)器向?yàn)g覽器傳送cookie的時(shí)候,很容易被劫持,并不是絕對(duì)的安全,還有一點(diǎn)就是,在大型的項(xiàng)目中,服務(wù)器往往不只一臺(tái),如果第一次請(qǐng)求,用戶信息被保存在了服務(wù)器1的session空間中,但是第二次請(qǐng)求被分流到了服務(wù)器2,這樣就獲取不到用戶信息了,依然要重新登錄,所以又引出了另一種方法:token來(lái)實(shí)現(xiàn)。
第二種,使用token安全令牌
實(shí)現(xiàn)原理:當(dāng)用戶請(qǐng)求頁(yè)面,輸入用戶信息,服務(wù)端經(jīng)過(guò)驗(yàn)證后,會(huì)生成一個(gè)token安全令牌(隨機(jī)字符串),并返回給客戶端,當(dāng)客戶端發(fā)送下一次請(qǐng)求的時(shí)候,直接攜帶這個(gè)token,服務(wù)端識(shí)別后,就可以直接訪問(wèn)頁(yè)面,不需要再次登錄了
優(yōu)點(diǎn):token只是以字符串的形式存在,不要服務(wù)器再開(kāi)辟空間,并且相對(duì)更安全,即使在傳輸?shù)倪^(guò)程中被劫持,別人也并不能破解內(nèi)容,并且減少了服務(wù)器壓力,減少頻繁的查詢數(shù)據(jù)庫(kù)。
泛型是什么?
就是一種不確定的輸出類型,只有需要在使用這個(gè)類的時(shí)候才能夠確定出來(lái)
泛型的好處:
靜態(tài)屬性與普通屬性的區(qū)別是什么?
靜態(tài)屬性 程序一加載時(shí) 就初始化,只有一份
實(shí)例屬性 需要實(shí)例化后 才加載
throw 和 throws 的區(qū)別?
throw:是真實(shí)拋出一個(gè)異常。
throws:是聲明可能會(huì)拋出一個(gè)異常。
final、finally、finalize 有什么區(qū)別?
final
final關(guān)鍵字主要用在三個(gè)地方:變量、方法、類;
final修飾的變量是常量不能被修改;
final修飾的方法是私有(private)不可被調(diào)用;
final修飾的類不能被繼承,類中的所有成員方法都被指定為final方法;
finally
finally:是 try{} catch{} finally{} 最后一部分,表示不論發(fā)生任何情況都會(huì)執(zhí)行,finally 部分可以省略,但如果 finally 部分存在,則一定會(huì)執(zhí)行 finally 里面的代碼。
finalize
finalize: 是 Object 類的一個(gè)方法,在垃圾收集器執(zhí)行的時(shí)候會(huì)調(diào)用被回收對(duì)象的此方法。
說(shuō)一下堆棧的區(qū)別?
功能方面:堆是用來(lái)存放對(duì)象的,棧是用來(lái)執(zhí)行程序的。
共享性:堆是線程共享的,棧是線程私有的。
空間大小:堆大小遠(yuǎn)遠(yuǎn)大于棧。
局部變量是存放在棧中,還是存放在堆棧中?
局部變量存放在棧中。
程序bai運(yùn)行中有兩個(gè)存儲(chǔ)空間可用du,一個(gè)是棧,是zhi歸屬于進(jìn)程本身的,另外一個(gè)是堆,所有dao進(jìn)程共用的。
局部變量在聲明周期為函數(shù)內(nèi)部,其存儲(chǔ)空間位于棧中。當(dāng)進(jìn)入函數(shù)時(shí),會(huì)對(duì)根據(jù)局部變量需求,在棧上申請(qǐng)一段內(nèi)存空間,供局部變量使用。當(dāng)局部變量生命周期結(jié)束后,在棧上釋放。
由于進(jìn)程的棧空間是有限的,所以要避免申請(qǐng)占用空間過(guò)大的局部變量,以及避免函數(shù)嵌套層數(shù)過(guò)多。這些都可能引起棧空間不夠?qū)е鲁绦虮罎ⅰ?/p>
框架
Spring
spring的15個(gè)經(jīng)典面試題:https://www.cnblogs.com/yanggb/p/11004887.html
Spring是什么?
Spring 是一個(gè)開(kāi)源框架,為簡(jiǎn)化企業(yè)級(jí)應(yīng)用開(kāi)發(fā)而生,目標(biāo)是使得Java EE應(yīng)用程序的開(kāi)發(fā)更加簡(jiǎn)捷,
Spring有哪些優(yōu)點(diǎn)?
輕量級(jí):Spring在大小和透明性方面絕對(duì)屬于輕量級(jí)的,基礎(chǔ)版本的Spring框架大約只有2MB。
控制反轉(zhuǎn)(IOC):Spring使用控制反轉(zhuǎn)技術(shù)實(shí)現(xiàn)了松耦合。依賴被注入到對(duì)象,而不是創(chuàng)建或?qū)ふ乙蕾噷?duì)象。
面向切面編程(AOP): Spring支持面向切面編程,同時(shí)把應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)的服務(wù)分離開(kāi)來(lái)。
容器:Spring包含并管理應(yīng)用程序?qū)ο蟮呐渲眉吧芷凇?br /> MVC框架:Spring的web框架是一個(gè)設(shè)計(jì)優(yōu)良的web MVC框架,很好的取代了一些web框架。
事務(wù)管理:Spring對(duì)下至本地業(yè)務(wù)上至全局業(yè)務(wù)(JAT)提供了統(tǒng)一的事務(wù)管理接口。
異常處理:Spring提供一個(gè)方便的API將特定技術(shù)的異常(由JDBC, Hibernate, 或JDO拋出)轉(zhuǎn)化為一致的、Unchecked異常。
AOP
AOP(面向切面編程)能夠將那些與業(yè)務(wù)無(wú)關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任封裝起來(lái),便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來(lái)的可擴(kuò)展性和可維護(hù)性。
用于:事務(wù)處理、日志管理、權(quán)限控制
IOC
IOC(控制反轉(zhuǎn))是一種設(shè)計(jì)思想,就是將原本在程序中手動(dòng)創(chuàng)建對(duì)象的控制權(quán),交由給Spring框架來(lái)管理。IOC在其他語(yǔ)言中也有應(yīng)用,并非Spring特有。IOC容器是Spring用來(lái)實(shí)現(xiàn)IOC的載體,IOC容器實(shí)際上就是一個(gè)Map(key,value),Map中存放的是各種對(duì)象。
將對(duì)象之間的相互依賴關(guān)系交給IOC容器來(lái)管理,并由IOC容器完成對(duì)象的注入。這樣可以很大程度上簡(jiǎn)化應(yīng)用的開(kāi)發(fā),把應(yīng)用從復(fù)雜的依賴關(guān)系中解放出來(lái)。IOC容器就像是一個(gè)工廠一樣,當(dāng)我們需要?jiǎng)?chuàng)建一個(gè)對(duì)象的時(shí)候,只需要配置好配置文件/注解即可,完全不用考慮對(duì)象是如何被創(chuàng)建出來(lái)的。在實(shí)際項(xiàng)目中一個(gè)Service類可能由幾百甚至上千個(gè)類作為它的底層,假如我們需要實(shí)例化這個(gè)Service,可能要每次都搞清楚這個(gè)Service所有底層類的構(gòu)造函數(shù),這可能會(huì)把人逼瘋。如果利用IOC的話,你只需要配置好,然后在需要的地方引用就行了,大大增加了項(xiàng)目的可維護(hù)性且降低了開(kāi)發(fā)難度。
也可理解為工廠模式+反射,不過(guò)工廠模式的對(duì)象生成是提前在工廠類中定死的,IOC更加靈活
什么是 ORM 框架?
ORM(Object Relation Mapping)對(duì)象關(guān)系映射,是把數(shù)據(jù)庫(kù)中的關(guān)系數(shù)據(jù)映射成為程序中的對(duì)象。
使用 ORM 的優(yōu)點(diǎn):提高了開(kāi)發(fā)效率降低了開(kāi)發(fā)成本、開(kāi)發(fā)更簡(jiǎn)單更對(duì)象化、可移植更強(qiáng)。
注解是怎么生效的?
Spring會(huì)掃描所有的類包,反射獲取到類里面的注解,對(duì)注解進(jìn)行邏輯判斷,獲取到進(jìn)行分析,不同的注解有不同的邏輯
Spring事務(wù)的實(shí)現(xiàn)方式和實(shí)現(xiàn)原理
Spring事務(wù)的本質(zhì)其實(shí)就是數(shù)據(jù)庫(kù)對(duì)事務(wù)的支持,沒(méi)有數(shù)據(jù)庫(kù)的事務(wù)支持,spring是無(wú)法提供事務(wù)功能的。真正的數(shù)據(jù)庫(kù)層的事務(wù)提交和回滾是通過(guò)binlog或者redo log實(shí)現(xiàn)的。
基于 @Transactional 的聲明式事務(wù)管理
Spring事務(wù)管理的方式有幾種?
1.編程式事務(wù):在代碼中硬編碼(不推薦使用)。
2.聲明式事務(wù):在配置文件中配置(推薦使用),分為基于XML的聲明式事務(wù)和基于注解的聲明式事務(wù)。
聲明式事務(wù)管理建立在AOP之上的。其本質(zhì)是通過(guò)AOP功能,對(duì)方法前后進(jìn)行攔截,將事務(wù)處理的功能編織到攔截的方法中,也就是在目標(biāo)方法開(kāi)始之前加入一個(gè)事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。
spring 中的 bean 是線程安全的嗎?
spring 中的 bean 默認(rèn)是單例模式,Spring容器本身并沒(méi)有提供線程安全的策略,因此是否線程安全完全取決于Bean本身的特性
spring 事務(wù)實(shí)現(xiàn)方式有哪些?
1.基于 xml 配置文件的方式
2.注解方式(在類上添加 @Transaction 注解)
說(shuō)出Spring 或者 Springmvc中常用的5個(gè)注解,并解釋含義
log4j日志級(jí)別
DEBUG:輸出調(diào)試信息;指出細(xì)粒度信息事件對(duì)調(diào)試應(yīng)用程序是非常有幫助的。
INFO: 輸出提示信息;消息在粗粒度級(jí)別上突出強(qiáng)調(diào)應(yīng)用程序的運(yùn)行過(guò)程。
WARN: 輸出警告信息;表明會(huì)出現(xiàn)潛在錯(cuò)誤的情形。
ERROR:輸出錯(cuò)誤信息;指出雖然發(fā)生錯(cuò)誤事件,但仍然不影響系統(tǒng)的繼續(xù)運(yùn)行。
FATAL:輸出致命錯(cuò)誤;指出每個(gè)嚴(yán)重的錯(cuò)誤事件將會(huì)導(dǎo)致應(yīng)用程序的退出。
ALL level:打開(kāi)所有日志記錄開(kāi)關(guān);是最低等級(jí)的,用于打開(kāi)所有日志記錄。
OFF level:關(guān)閉所有日志記錄開(kāi)關(guān);是最高等級(jí)的,用于關(guān)閉所有日志記錄。
按照范圍從小到大排序:OFF level > FATAL > ERROR > WARN > INFO > DEBUG > ALL
level;范圍大的會(huì)包含范圍小的,例如日志設(shè)置為INFO級(jí)別的話則FATAL、ERROR、WARN、INFO的日志開(kāi)關(guān)都是打開(kāi)的,而DEBUG的日志開(kāi)關(guān)將是關(guān)閉的。
Log4j建議只使用四個(gè)級(jí)別,優(yōu)先級(jí)從高到低分別是 ERROR、WARN、INFO、DEBUG。
SpringBoot
SpringBoot是什么?
簡(jiǎn)單版:
用來(lái)簡(jiǎn)化spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程
使用特定的方式來(lái)進(jìn)行配置(properties或yml文件)
main方法運(yùn)行
嵌入的Tomcat 無(wú)需部署war文件
簡(jiǎn)化maven配置
自動(dòng)配置spring添加對(duì)應(yīng)功能starter自動(dòng)化配置
spring boot來(lái)簡(jiǎn)化spring應(yīng)用開(kāi)發(fā),約定大于配置,去繁從簡(jiǎn),just run就能創(chuàng)建一個(gè)獨(dú)立的,產(chǎn)品級(jí)別的應(yīng)用
復(fù)雜版(改):
Spring Boot 是 Spring 開(kāi)源組織下的子項(xiàng)目,是 Spring 組件一站式解決方案,主要是簡(jiǎn)化了使用 Spring 的難度,簡(jiǎn)省了繁重的配置,提供了各種啟動(dòng)器,開(kāi)發(fā)者能快速上手。
1、獨(dú)立運(yùn)行
Spring Boot而且內(nèi)嵌了各種servlet容器,Tomcat、Jetty等,現(xiàn)在不再需要打成war包部署到容器中,Spring Boot只要打成一個(gè)可執(zhí)行的jar包就能獨(dú)立運(yùn)行,所有的依賴包都在一個(gè)jar包內(nèi)。
2、簡(jiǎn)化配置
spring-boot-starter-web啟動(dòng)器自動(dòng)依賴其他組件,簡(jiǎn)少了maven的配置。除此之外,還提供了各種啟動(dòng)器,開(kāi)發(fā)者能快速上手。
3、自動(dòng)配置
Spring Boot能根據(jù)當(dāng)前類路徑下的類、jar包來(lái)自動(dòng)配置bean,如添加一個(gè)spring-boot-starter-web啟動(dòng)器就能擁有web的功能,無(wú)需其他配置。
4、無(wú)代碼生成和XML配置
Spring Boot配置過(guò)程中無(wú)代碼生成,也無(wú)需XML配置文件就能完成所有配置工作,這一切都是借助于條件注解完成的,這也是Spring4.x的核心功能之一。
5、應(yīng)用監(jiān)控
Spring Boot提供一系列端點(diǎn)可以監(jiān)控服務(wù)及應(yīng)用,做健康檢測(cè)。
Spring Boot 的配置文件有哪幾種格式?它們有什么區(qū)別?
.properties 和 .yml,它們的區(qū)別主要是書寫格式不同。
springboot事務(wù)是怎么去控制的 / 實(shí)現(xiàn)管理事務(wù)的?
我們以前沒(méi)有spring的時(shí)候,都是手動(dòng)報(bào)錯(cuò)就rollback的,現(xiàn)在有了spring,底層實(shí)現(xiàn)是用了aop 創(chuàng)建代理對(duì)象,就可以產(chǎn)生事務(wù)了
Spring Boot 的核心注解是哪個(gè)?它主要由哪幾個(gè)注解組成的?
啟動(dòng)類上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要組合包含了以下 3 個(gè)注解:
@SpringBootConfiguration:組合了 @Configuration 注解,實(shí)現(xiàn)配置文件的功能。
@EnableAutoConfiguration:打開(kāi)自動(dòng)配置的功能,也可以關(guān)閉某個(gè)自動(dòng)配置的選項(xiàng),如關(guān)閉數(shù)據(jù)源自動(dòng)配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。
@ComponentScan:Spring組件包名掃描。
SpringBoot 常用注解
1.@RestController 和 @RequestMapping 注解
2.@SpringBootApplication
3.@ResponseBody @RequestParam
4.@AutoWired
5.@PathVariable
Spring Boot 注冊(cè)bean的方法
@ComponentScan
@Bean
@Import
SpringBoot注入依賴及注解
常用注解
@Service用于標(biāo)注業(yè)務(wù)層組件
@Controller用于標(biāo)注控制層組件
@Repository用于標(biāo)注數(shù)據(jù)庫(kù)訪問(wèn)Dao組件
@Component泛指組件,當(dāng)組件不好歸類的時(shí)候,我們可以使用這個(gè)注解進(jìn)行標(biāo)注
@Autowired,自動(dòng)注入,自動(dòng)從spring的上下文找到合適的bean來(lái)注入
@RestController,Spring4之后新加入的注解,原來(lái)返回json需要@ResponseBody和@Controller配合,將調(diào)用的結(jié)果直接返回給調(diào)用者。
@Value:注入Spring boot application.properties配置的屬性的值。
@RequestMapping:提供路由信息,負(fù)責(zé)URL到Controller中的具體函數(shù)的映射。@RequestMapping(“/path”)表示該控制器處理所有“/path”的UR L請(qǐng)求。RequestMapping是一個(gè)用來(lái)處理請(qǐng)求地址映射的注解,可用于類或方法上。
@GetMapping是一個(gè)組合注解,是@RequestMapping(method = RequestMethod.GET)的縮寫。該注解將HTTP Get 映射到 特定的處理方法上。
同理PostMapping也是一個(gè)組合注解,是@RequestMapping(method = RequestMethod.POST)的縮寫。
@PathVariable:獲取url中的數(shù)據(jù)。
@ComponentScan 組件掃描,發(fā)現(xiàn)和組裝一些Bean。
@EnableAutoConfiguration自動(dòng)配置。
@SpringBootApplication:申明讓spring boot自動(dòng)給程序進(jìn)行必要的配置,這個(gè)配置等同于:@Configuration ,@EnableAutoConfiguration 和 @ComponentScan 三個(gè)配置。
@Data 自動(dòng)生成setter、getter方法
@Import:用來(lái)導(dǎo)入其他配置類。
@ImportResource:用來(lái)加載xml配置文件。
@Bean:放在方法的上面,而不是類,意思是產(chǎn)生一個(gè)bean,并交給spring管理。
@Inject:等價(jià)于默認(rèn)的@Autowired,只是沒(méi)有required屬性;
Spring Boot 自動(dòng)配置原理是什么?
注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自動(dòng)配置的核心,首先它得是一個(gè)配置文件,其次根據(jù)類路徑下是否有這個(gè)類去自動(dòng)配置。
Springboot里面哪些注解屬于單例模式?
@AutoWired
@Controller和@RestController的區(qū)別
springboot常用的starter有哪些?
1.spring-boot-starter-web (嵌入tomcat和web開(kāi)發(fā)需要servlet與jsp支持)
2.spring-boot-starter-data-jpa (數(shù)據(jù)庫(kù)支持)
3.spring-boot-starter-data-redis (redis數(shù)據(jù)庫(kù)支持)
4.spring-boot-starter-data-solr (solr搜索應(yīng)用框架支持)
5.mybatis-spring-boot-starter (第三方的mybatis集成starter)
Mybatis
Mybatis模糊查詢用#和$什么區(qū)別
簡(jiǎn)述Mybatis提供的兩級(jí)緩存,以及緩存的查找順序
參考:https://juejin.cn/post/6926161053743218695
一級(jí)緩存是SqlSession級(jí)別的緩存。在操作數(shù)據(jù)庫(kù)時(shí)需要構(gòu)造sqlSession對(duì)象,底層實(shí)際上是在對(duì)象中有一個(gè)數(shù)據(jù)結(jié)構(gòu)(HashMap)用于存儲(chǔ)緩存數(shù)據(jù)。不同的sqlSession之間的緩存數(shù)據(jù)區(qū)域(HashMap)是互相不影響的。
二級(jí)緩存是mapper級(jí)別的緩存,多個(gè)SqlSession去操作同一個(gè)Mapper的sql語(yǔ)句,多個(gè)SqlSession可以共用二級(jí)緩存,二級(jí)緩存是跨SqlSession的。
緩存的查找順序:二級(jí)緩存 => 一級(jí)緩存 => 數(shù)據(jù)庫(kù)
一級(jí)緩存是SqlSession級(jí)別的
一級(jí)緩存默認(rèn)開(kāi)啟
一級(jí)緩存在底層update方法也就是刪除 新增 更新 時(shí)候會(huì)清除一級(jí)緩存;
一級(jí)緩存在查詢的時(shí)候會(huì)先從緩存中查詢,沒(méi)查到去查db,然后再放入本地一級(jí)緩存;
一級(jí)緩存之前會(huì)先從二級(jí)緩存查,沒(méi)查到再去一級(jí)查,一級(jí)沒(méi)查到再去db查;
SpringCloud
springCloud是什么?
SpringCloud是基于SpringBoot的一套實(shí)現(xiàn)微服務(wù)的框架。它提供了微服務(wù)開(kāi)發(fā)所需的配置管理、服務(wù)發(fā)現(xiàn)、斷路器、智能路由、微代理、控制總線、全局鎖、決策競(jìng)選、分布式會(huì)話和集群狀態(tài)管理等組件。最重要的是,跟SpringBoot框架一起使用的話,會(huì)讓你開(kāi)發(fā)微服務(wù)架構(gòu)的云服務(wù)非常方便。
SpringCloud五大核心組件:
服務(wù)注冊(cè)發(fā)現(xiàn)-Netflix Eureka
配置中心 - spring cloud config
負(fù)載均衡-Netflix Ribbon
斷路器 - Netflix Hystrix
路由(網(wǎng)關(guān)) - Netflix Zuul
spring cloud 斷路器的作用是什么?
在分布式架構(gòu)中,斷路器模式的作用也是類似的,當(dāng)某個(gè)服務(wù)單元發(fā)生故障(類似用電器發(fā)生短路)之后,通過(guò)斷路器的故障監(jiān)控(類似熔斷保險(xiǎn)絲),向調(diào)用方返回一個(gè)錯(cuò)誤響應(yīng),而不是長(zhǎng)時(shí)間的等待。這樣就不會(huì)使得線程因調(diào)用故障服務(wù)被長(zhǎng)時(shí)間占用不釋放,避免了故障在分布式系統(tǒng)中的蔓延。
spring cloud 的核心組件有哪些?
Eureka:服務(wù)注冊(cè)于發(fā)現(xiàn)。
Feign:(負(fù)載均衡)一個(gè)輕量級(jí)Restful的HTTP服務(wù)客戶端,Feign內(nèi)置了Ribbon,用來(lái)做客戶端負(fù)載均衡,去調(diào)用服務(wù)注冊(cè)中心的服務(wù)。Feign的使用方式是:使用Feign的注解定義接口,調(diào)用這個(gè)接口,就可以調(diào)用服務(wù)注冊(cè)中心的服務(wù)
Hystrix:提供線程池,不同的服務(wù)走不同的線程池,實(shí)現(xiàn)了不同服務(wù)調(diào)用的隔離,避免了服務(wù)雪崩的問(wèn)題。
Zuul:網(wǎng)關(guān)管理,由 Zuul 網(wǎng)關(guān)轉(zhuǎn)發(fā)請(qǐng)求給對(duì)應(yīng)的服務(wù)。
高并發(fā)
高并發(fā)解決方案案例
常用的高并發(fā)處理的思路與手段
從服務(wù)端視角看高并發(fā)
服務(wù)端處理請(qǐng)求需要耗費(fèi)服務(wù)端的資源,比如能同時(shí)開(kāi)啟的進(jìn)程數(shù)、能同時(shí)運(yùn)行的線程數(shù)、網(wǎng)絡(luò)連接數(shù)、cpu、I/O、內(nèi)存等等,由于服務(wù)端資源是有限的,那么服務(wù)端能同時(shí)處理的請(qǐng)求也是有限的。高并發(fā)問(wèn)題的本質(zhì)就是:資源的有限性
高并發(fā)帶來(lái)的問(wèn)題
服務(wù)端的處理和響應(yīng)會(huì)越來(lái)越慢,甚至?xí)G棄部分請(qǐng)求不予處理,更嚴(yán)重的會(huì)導(dǎo)致服務(wù)端崩潰。
高并發(fā)處理的基本思路
1)從客戶端看
- 盡量減少請(qǐng)求數(shù)量,比如:依靠客戶端自身的緩存或處理能力
- 盡量減少對(duì)服務(wù)端資源的不必要耗費(fèi),比如:重復(fù)使用某些資源,如連接池客戶端處理的基本原則就是:能不訪問(wèn)服務(wù)端就不要訪問(wèn)
2)從服務(wù)端看
- 增加資源供給,比如:更大的網(wǎng)絡(luò)帶寬,使用更高配置的服務(wù)器,使用高性能的Web服務(wù)器,使用高性能的數(shù)據(jù)庫(kù)
- 請(qǐng)求分流,比如:使用集群,分布式的系統(tǒng)架構(gòu)
- 應(yīng)用優(yōu)化,比如:使用更高效的編程語(yǔ)言,優(yōu)化處理業(yè)務(wù)邏輯的算法,優(yōu)化訪問(wèn)數(shù)據(jù)庫(kù)的SQL
基本原則:分而治之,并提高單個(gè)請(qǐng)求的處理速度
高并發(fā)處理的基本手段
1)客戶端發(fā)出請(qǐng)求層面,常見(jiàn)的手段有:
- 盡量利用瀏覽器的緩存功能,減少訪問(wèn)服務(wù)端,比如:js、css、圖片等
- 可以考慮使用壓縮傳輸?shù)墓δ?#xff0c;減少網(wǎng)絡(luò)流量,也會(huì)提高傳輸速度
- 考慮使用異步請(qǐng)求,分批獲取數(shù)據(jù)
2)前端接收客戶端請(qǐng)求層面,常見(jiàn)的手段有:
- 動(dòng)靜分離,部分靜態(tài)資源可以直接從Nginx返回
- 按請(qǐng)求的不同,分發(fā)到不同的后端進(jìn)行處理,比如:負(fù)載均衡、業(yè)務(wù)拆分訪問(wèn)等
- 前面再加上一層來(lái)做多個(gè)Nginx的負(fù)載均衡,比如:LVS、F5等
- 還可以在更前面使用CDN服務(wù)
- 還可以對(duì)動(dòng)態(tài)內(nèi)容進(jìn)行緩存,盡量減少訪問(wèn)后端服務(wù)
3)Web服務(wù)器層面,常見(jiàn)的手段有:
- 使用最新的JVM,并進(jìn)行配置優(yōu)化
- 對(duì)Web服務(wù)器進(jìn)行配置優(yōu)化,比如:調(diào)整內(nèi)存數(shù)量、線程數(shù)量等
- 提供多個(gè)能提供相同服務(wù)的Web服務(wù)器,以實(shí)現(xiàn)負(fù)載均衡
- 仔細(xì)規(guī)劃Web服務(wù)器上部署的應(yīng)用規(guī)模
- 對(duì)Web服務(wù)器進(jìn)行集群
4)Web應(yīng)用層面,常見(jiàn)的手段有:
- 動(dòng)態(tài)內(nèi)容靜態(tài)化
- Java開(kāi)發(fā)優(yōu)化
- 優(yōu)化處理業(yè)務(wù)邏輯的算法
- 合理高效的利用緩存
- 優(yōu)化訪問(wèn)數(shù)據(jù)庫(kù)的Sql,可以考慮利用存儲(chǔ)過(guò)程等數(shù)據(jù)庫(kù)的能力
- 合理使用多線程,加快業(yè)務(wù)處理
- 部分業(yè)務(wù)可以考慮內(nèi)存數(shù)據(jù)庫(kù),或者是進(jìn)行純內(nèi)存處理
- 盡量避免遠(yuǎn)程調(diào)用、大量I/O等耗時(shí)的操作
- 合理規(guī)劃事務(wù)等較為耗資源的操作
- 合理使用異步處理
- 對(duì)部分業(yè)務(wù)考慮采用預(yù)處理或者預(yù)計(jì)算的方式,減少實(shí)時(shí)計(jì)算量
- 內(nèi)部系統(tǒng)間的業(yè)務(wù)盡量直接調(diào)用、直接處理,減少WebService、工作流等
5)數(shù)據(jù)庫(kù)層面,常見(jiàn)的手段有:
- 合理選擇數(shù)據(jù)庫(kù)的引擎,比如Mysql的InnoDB與MyISAM引擎
- 進(jìn)行配置優(yōu)化
- 可以考慮使用存儲(chǔ)過(guò)程來(lái)處理復(fù)雜的數(shù)據(jù)邏輯
- 數(shù)據(jù)庫(kù)集群,進(jìn)行讀寫分離
- 合理設(shè)計(jì)數(shù)據(jù)庫(kù)的表結(jié)構(gòu)、索引等
- 分庫(kù)、分表,降低單庫(kù)、單表的數(shù)據(jù)量
數(shù)據(jù)庫(kù)
索引
比較好的面試題 https://www.cnblogs.com/williamjie/p/11187470.html
什么是索引?(為什么需要使用索引)
【簡(jiǎn)單】:
索引其實(shí)是一種數(shù)據(jù)結(jié)構(gòu),能夠幫助我們快速的檢索數(shù)據(jù)庫(kù)中的數(shù)據(jù)
【復(fù)雜】:
MySQL官方對(duì)索引的定義為:索引(Index)是幫助 MySQL 高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
打個(gè)比方,如果合理的設(shè)計(jì)且使用索引的MySQL是一輛蘭博基尼的話,那么沒(méi)有設(shè)計(jì)和使用索引的MySQL就是一個(gè)人力三輪車。
索引分單列索引和組合索引。單列索引,即一個(gè)索引只包含單個(gè)列,一個(gè)表可以有多個(gè)單列索引,但這不是組合索引。組合索引,即一個(gè)索引包含多個(gè)列。
創(chuàng)建索引時(shí),你需要確保該索引是應(yīng)用在 SQL 查詢語(yǔ)句的條件(一般作為 WHERE 子句的條件)。
實(shí)際上,索引也是一張表,該表保存了主鍵與索引字段,并指向?qū)嶓w表的記錄。
上面都在說(shuō)使用索引的好處,但過(guò)多的使用索引將會(huì)造成濫用。因此索引也會(huì)有它的缺點(diǎn):雖然索引大大提高了查詢速度,同時(shí)卻會(huì)降低更新表的速度,如對(duì)表進(jìn)行INSERT、UPDATE和DELETE。因?yàn)楦卤頃r(shí),MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件。
建立索引會(huì)占用磁盤空間的索引文件。
索引具體采用的哪種數(shù)據(jù)結(jié)構(gòu)
常見(jiàn)的MySQL主要有兩種結(jié)構(gòu):Hash索引和B+ Tree索引,我們使用的是InnoDB引擎,默認(rèn)的是B+樹(shù)
既然你提到InnoDB使用的B+ 樹(shù)的索引模型,那么你知道為什么采用B+ 樹(shù)嗎?這和Hash索引比較起來(lái)有什么優(yōu)缺點(diǎn)嗎?
因?yàn)镠ash索引底層是哈希表,哈希表是一種以key-value存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),所以多個(gè)數(shù)據(jù)在存儲(chǔ)關(guān)系上是完全沒(méi)有任何順序關(guān)系的,所以,對(duì)于區(qū)間查詢是無(wú)法直接通過(guò)索引查詢的,就需要全表掃描。所以,哈希索引只適用于等值查詢的場(chǎng)景。而B(niǎo)+ 樹(shù)是一種多路平衡查詢樹(shù),所以他的節(jié)點(diǎn)是天然有序的(左子節(jié)點(diǎn)小于父節(jié)點(diǎn)、父節(jié)點(diǎn)小于右子節(jié)點(diǎn)),所以對(duì)于范圍查詢的時(shí)候不需要做全表掃描
優(yōu)化
SQL語(yǔ)句優(yōu)化
分庫(kù)分表
1)分庫(kù)分表,如何對(duì)數(shù)據(jù)庫(kù)如何進(jìn)行垂直拆分或水平拆分的,用什么中間件?
綜上,現(xiàn)在其實(shí)建議考量的,就是 Sharding-jdbc 和 Mycat,這兩個(gè)都可以去考慮使用。
Sharding-jdbc 這種 client 層方案的優(yōu)點(diǎn)在于不用部署,運(yùn)維成本低,不需要代理層的二次轉(zhuǎn)發(fā)請(qǐng)求,性能很高,但是如果遇到升級(jí)啥的需要各個(gè)系統(tǒng)都重新升級(jí)版本再發(fā)布,各個(gè)系統(tǒng)都需要耦合 Sharding-jdbc 的依賴;
Mycat 這種 proxy 層方案的缺點(diǎn)在于需要部署,自己運(yùn)維一套中間件,運(yùn)維成本高,但是好處在于對(duì)于各個(gè)項(xiàng)目是透明的,如果遇到升級(jí)之類的都是自己中間件那里搞就行了。
2)分庫(kù)分表之后,id 主鍵如何處理?、、
----snowflake 雪花算法 (id work)
3)從未分庫(kù)分表動(dòng)態(tài)切換到分庫(kù)分表上?
a、停機(jī)遷移,寫個(gè)公告凌晨升級(jí)(半夜) --> 寫個(gè)工具從0點(diǎn)開(kāi)始讀寫數(shù)據(jù),4點(diǎn)伸個(gè)懶腰下班,爽
b、雙寫遷移方案
讀寫分離
前提:讀并發(fā)大
就是寫一個(gè)主庫(kù),但是主庫(kù)掛多個(gè)從庫(kù),然后從多個(gè)從庫(kù)來(lái)讀,那不就可以支撐更高的讀并發(fā)壓力了嗎?
? 主庫(kù)將變更寫入 binlog 日志,然后從庫(kù)連接到主庫(kù)之后,從庫(kù)有一個(gè) IO 線程,將主庫(kù)的 binlog 日志拷貝到自己本地,寫入一個(gè) relay 中繼日志中。接著從庫(kù)中有一個(gè) SQL 線程會(huì)從中繼日志讀取 binlog,然后執(zhí)行 binlog 日志中的內(nèi)容,也就是在自己本地再次執(zhí)行一遍 SQL,這樣就可以保證自己跟主庫(kù)的數(shù)據(jù)是一樣的。
Mysql和Oracle有什么區(qū)別?
1.Oracle收費(fèi),Mysql免費(fèi)
2.單引號(hào)的處理
Mysql里可以用雙引號(hào)包起字符串,Oracle里只可以用單引號(hào)包起字符串。在插入和修改字符串前必須做單引號(hào)的替換:把所有出現(xiàn)的一個(gè)單引號(hào)替換成兩個(gè)單引號(hào)。
3.自動(dòng)增長(zhǎng)的數(shù)據(jù)類型處理
Mysql是一個(gè)自動(dòng)增長(zhǎng)的數(shù)據(jù)類型,插入數(shù)據(jù)的時(shí)候,不需要管理,它自己會(huì)自動(dòng)增長(zhǎng),Oracle不支持自動(dòng)增長(zhǎng)的數(shù)據(jù)類型,通過(guò)建立一個(gè)自動(dòng)增長(zhǎng)的序列號(hào)來(lái)完成自動(dòng)增長(zhǎng)。
4.事物提交方式
oracle默認(rèn)不自動(dòng)提交,需要用戶手動(dòng)提交。
Mysql默認(rèn)是自動(dòng)提交。不支持事物。
Mysql默認(rèn)自動(dòng)提交,也就是你提交一個(gè)query,他就直接執(zhí)行,我們可以通過(guò)
set autocommit=0 禁止自動(dòng)提交
set autocommit=1 開(kāi)啟自動(dòng)提交
group by后面還可以加什么
group by 對(duì)應(yīng)的列如果如果需要加條件,一般用having。
MySQL
MySQL的事務(wù)
事務(wù)的基本要素(ACID):
1、原子性(Atomicity):
事務(wù)開(kāi)始后所有操作,要么全部做完,要么全部不做,不可能停滯在中間環(huán)節(jié)。事務(wù)執(zhí)行過(guò)程中出錯(cuò),會(huì)回滾到事務(wù)開(kāi)始前的狀態(tài),所有的操作就像沒(méi)有發(fā)生一樣。也就是說(shuō)事務(wù)是一個(gè)不可分割的整體,就像化學(xué)中學(xué)過(guò)的原子,是物質(zhì)構(gòu)成的基本單位
2、一致性(Consistency):
事務(wù)開(kāi)始前和結(jié)束后,數(shù)據(jù)庫(kù)的完整性約束沒(méi)有被破壞 。比如A向B轉(zhuǎn)賬,不可能A扣了錢,B卻沒(méi)收到。
3、隔離性(Isolation):
同一時(shí)間,只允許一個(gè)事務(wù)請(qǐng)求同一數(shù)據(jù),不同的事務(wù)之間彼此沒(méi)有任何干擾。比如A正在從一張銀行卡中取錢,在A取錢的過(guò)程結(jié)束前,B不能向這張卡轉(zhuǎn)賬。
4、持久性(Durability):
事務(wù)完成后,事務(wù)對(duì)數(shù)據(jù)庫(kù)的所有更新將被保存到數(shù)據(jù)庫(kù),不能回滾。
事務(wù)的并發(fā)問(wèn)題:
臟讀:事務(wù)A讀取了事務(wù)B更新的數(shù)據(jù),然后B回滾操作,那么A讀取到的數(shù)據(jù)是臟數(shù)據(jù)
不可重復(fù)讀:事務(wù) A 多次讀取同一數(shù)據(jù),事務(wù) B 在事務(wù)A多次讀取的過(guò)程中,對(duì)數(shù)據(jù)作了更新并提交,導(dǎo)致事務(wù)A多次讀取同一數(shù)據(jù)時(shí),結(jié)果 不一致
幻讀:系統(tǒng)管理員A將數(shù)據(jù)庫(kù)中所有學(xué)生的成績(jī)從具體分?jǐn)?shù)改為ABCDE等級(jí),但是系統(tǒng)管理員B就在這個(gè)時(shí)候插入了一條具體分?jǐn)?shù)的記錄,當(dāng)系統(tǒng)管理員A改結(jié)束后發(fā)現(xiàn)還有一條記錄沒(méi)有改過(guò)來(lái),就好像發(fā)生了幻覺(jué)一樣,這就叫幻讀。
小結(jié):
不可重復(fù)讀的和幻讀很容易混淆,不可重復(fù)讀側(cè)重于修改,幻讀側(cè)重于新增或刪除。解決不可重復(fù)讀的問(wèn)題只需鎖住滿足條件的行,解決幻讀需要鎖表
MySQL事務(wù)隔離級(jí)別:
四種:未提交讀、已提交讀、可重復(fù)讀、可串行化,
默認(rèn)是 可重復(fù)讀
如何做 MySQL 的性能優(yōu)化?
怎么確定有沒(méi)有用到索引
使用方法,在select語(yǔ)句前加上explain就可以了:
如:
explain select surname,first_name from a,b where a.id=b.id
細(xì)節(jié):https://www.cnblogs.com/the-fool/p/11113996.html
Redis
Redis是什么及特點(diǎn)
Redis是一個(gè)內(nèi)存型緩存數(shù)據(jù)庫(kù)
特點(diǎn):
key/value型數(shù)據(jù)庫(kù)
支持豐富的數(shù)據(jù)類型(String,List,Set,ZSet,Hash)
支持持久化,內(nèi)存數(shù)據(jù),持久化到硬盤中
是單進(jìn)程,單線程,所以是線程安全
可實(shí)現(xiàn)分布式鎖
Redis除了緩存還能做什么
比如:用戶登錄session,網(wǎng)頁(yè)緩存,日志系統(tǒng),搜索引擎,消息隊(duì)列、持久化、發(fā)布訂閱系統(tǒng)、計(jì)時(shí)器、計(jì)數(shù)器(瀏覽量!)
Redis 有哪些功能?
數(shù)據(jù)緩存功能
分布式鎖的功能
支持?jǐn)?shù)據(jù)持久化
支持事務(wù)
支持消息隊(duì)列
一個(gè)字符串類型的值能存儲(chǔ)最大容量是多少?
512M
最大能存多大?
官方說(shuō)單例能處理key:2.5億個(gè)
線程安全嗎?
Redis是個(gè)單線程程序,所以它是線程安全的。
redis 存儲(chǔ)結(jié)構(gòu)
key-value
redis的基本數(shù)據(jù)類型
string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。”
怎么理解Redis事務(wù)?
事務(wù)是一個(gè)單獨(dú)的隔離操作:事務(wù)中的所有命令都會(huì)序列化、按順序地執(zhí)行。事務(wù)在執(zhí)行的過(guò)程中,不會(huì)被其他客戶端發(fā)送來(lái)的命令請(qǐng)求所打斷。
事務(wù)是一個(gè)原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行。
什么是Redis持久化?Redis有哪幾種持久化方式?優(yōu)缺點(diǎn)是什么?
持久化就是把內(nèi)存的數(shù)據(jù)寫到磁盤中去,防止服務(wù)宕機(jī)了內(nèi)存數(shù)據(jù)丟失。
RDB(Redis Database):指定的時(shí)間間隔能對(duì)你的數(shù)據(jù)進(jìn)行快照存儲(chǔ)。
AOF(Append Only File):每一個(gè)收到的寫命令都通過(guò)write函數(shù)追加到文件中。
什么情況下要用到緩存,什么數(shù)據(jù)適合緩存,使用緩存需要注意什么問(wèn)題?
熱點(diǎn)數(shù)據(jù),不變化的數(shù)據(jù)(如省市區(qū),分類),登錄用戶的token也可以用緩存,需要注意緩存和數(shù)據(jù)庫(kù)的一致性,緩存擊穿,緩存穿透,雪崩問(wèn)題
什么是緩存擊穿?怎么解決?
相較于緩存穿透,緩存擊穿的目的性更強(qiáng),一個(gè)存在的key,在緩存過(guò)期的一刻,同時(shí)有大量的請(qǐng)求,這些請(qǐng)求都會(huì)擊穿到DB,造成瞬時(shí)DB請(qǐng)求量大、壓力驟增。這就是緩存被擊穿,只是針對(duì)其中某個(gè)key的緩存不可用而導(dǎo)致?lián)舸?#xff0c;但是其他的key依然可以使用緩存響應(yīng)。
比如熱搜排行上,一個(gè)熱點(diǎn)新聞被同時(shí)大量訪問(wèn)就可能導(dǎo)致緩存擊穿。
在訪問(wèn)key之前,采用SETNX(set if not exists)來(lái)設(shè)置另一個(gè)短期key來(lái)鎖住當(dāng)前key的訪問(wèn),訪問(wèn)結(jié)束再刪除該短期key。保證同時(shí)刻只有一個(gè)線程訪問(wèn)。這樣對(duì)鎖的要求就十分高。
什么是緩存穿透?怎么解決?
緩存穿透:
緩存穿透的概念很簡(jiǎn)單,用戶想要查詢一個(gè)數(shù)據(jù),發(fā)現(xiàn)redis內(nèi)存數(shù)據(jù)庫(kù)沒(méi)有,也就是緩存沒(méi)有命中,于是向持久層數(shù)據(jù)庫(kù)查詢。發(fā)現(xiàn)也沒(méi)有,于是本次查詢失敗。當(dāng)用戶很多的時(shí)候,緩存都沒(méi)有命中(秒殺!),于是都去請(qǐng)求了持久層數(shù)據(jù)庫(kù)。這會(huì)給持久層數(shù)據(jù)庫(kù)造成很大的壓力,這時(shí)候就相當(dāng)于出現(xiàn)了緩存穿透。洪水攻擊。數(shù)據(jù)庫(kù)也查不到就沒(méi)有緩存,就會(huì)一直與數(shù)據(jù)庫(kù)訪問(wèn)。
解決方案:
對(duì)所有可能查詢的參數(shù)以Hash的形式存儲(chǔ),以便快速確定是否存在這個(gè)值,在控制層先進(jìn)行攔截校驗(yàn),校驗(yàn)不通過(guò)直接打回,減輕了存儲(chǔ)系統(tǒng)的壓力。
一次請(qǐng)求若在緩存和數(shù)據(jù)庫(kù)中都沒(méi)找到,就在緩存中方一個(gè)空對(duì)象用于處理后續(xù)這個(gè)請(qǐng)求。
什么是緩存雪崩?怎么解決?
大量的key設(shè)置了相同的過(guò)期時(shí)間,導(dǎo)致在緩存在同一時(shí)刻全部失效,造成瞬時(shí)DB請(qǐng)求量大、壓力驟增,引起雪崩。
解決方案:
這個(gè)思想的含義是,既然redis有可能掛掉,那我多增設(shè)幾臺(tái)redis,這樣一臺(tái)掛掉之后其他的還可以繼續(xù)工作,其實(shí)就是搭建的集群
這個(gè)解決方案的思想是,在緩存失效后,通過(guò)加鎖或者隊(duì)列來(lái)控制讀數(shù)據(jù)庫(kù)寫緩存的線程數(shù)量。比如對(duì)某個(gè)key只允許一個(gè)線程查詢數(shù)據(jù)和寫緩存,其他線程等待。
數(shù)據(jù)加熱的含義就是在正式部署之前,我先把可能的數(shù)據(jù)先預(yù)先訪問(wèn)一遍,這樣部分可能大量訪問(wèn)的數(shù)據(jù)就會(huì)加載到緩存中。在即將發(fā)生大并發(fā)訪問(wèn)前手動(dòng)觸發(fā)加載緩存不同的key,設(shè)置不同的過(guò)期時(shí)間,讓緩存失效的時(shí)間點(diǎn)盡量均勻。
怎么保證緩存和數(shù)據(jù)庫(kù)數(shù)據(jù)的一致性?
合理設(shè)置緩存的過(guò)期時(shí)間。
新增、更改、刪除數(shù)據(jù)庫(kù)操作時(shí)同步更新 Redis,可以使用事物機(jī)制來(lái)保證數(shù)據(jù)的一致性。
Redis悲觀鎖和樂(lè)觀鎖
悲觀鎖:
執(zhí)行操作前假設(shè)當(dāng)前的操作肯定(或有很大幾率)會(huì)被打斷(悲觀)。基于這個(gè)假設(shè),我們?cè)谧霾僮髑熬蜁?huì)把相關(guān)資源鎖定,不允許自己執(zhí)行期間有其他操作干擾。
Redis不支持悲觀鎖。Redis作為緩存服務(wù)器使用時(shí),以操作為主,很少寫操作,相應(yīng)的操作被打斷的幾率較少。不采用悲觀鎖是為了防止降低性能。
樂(lè)觀鎖:
執(zhí)行操作前假設(shè)當(dāng)前操作不會(huì)被打斷(樂(lè)觀)。基于這個(gè)假設(shè),我們?cè)谧霾僮髑安粫?huì)鎖定資源,萬(wàn)一發(fā)生了其他操作的干擾,那么本次操作將被放棄。
Redis 怎么實(shí)現(xiàn)分布式鎖?
Redis 分布式鎖其實(shí)就是在系統(tǒng)里面占一個(gè)“坑”,其他程序也要占“坑”的時(shí)候,占用成功了就可以繼續(xù)執(zhí)行,失敗了就只能放棄或稍后重試。
占坑一般使用 setnx(set if not exists)指令,只允許被一個(gè)程序占有,使用完調(diào)用 del 釋放鎖。
Redis 分布式鎖有什么缺陷?
Redis 分布式鎖不能解決超時(shí)的問(wèn)題,分布式鎖有一個(gè)超時(shí)時(shí)間,程序的執(zhí)行如果超出了鎖的超時(shí)時(shí)間就會(huì)出現(xiàn)問(wèn)題。
Redis 如何做內(nèi)存優(yōu)化?
盡量使用 Redis 的散列表,把相關(guān)的信息放到散列表里面存儲(chǔ),而不是把每個(gè)字段單獨(dú)存儲(chǔ),這樣可以有效的減少內(nèi)存使用。比如將 Web 系統(tǒng)的用戶對(duì)象,應(yīng)該放到散列表里面再整體存儲(chǔ)到 Redis,而不是把用戶的姓名、年齡、密碼、郵箱等字段分別設(shè)置 key 進(jìn)行存儲(chǔ)。
redis是單線程的,為什么那么快
1)完全基于內(nèi)存,絕大部分請(qǐng)求是純粹的內(nèi)存操作,非常快速。數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1)
2)數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,對(duì)數(shù)據(jù)操作也簡(jiǎn)單,Redis中的數(shù)據(jù)結(jié)構(gòu)是專門進(jìn)行設(shè)計(jì)的
3)采用單線程,避免了不必要的上下文切換和競(jìng)爭(zhēng)條件,也不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗 CPU,不用去考慮各種鎖的問(wèn)題,不存在加鎖釋放鎖操作,沒(méi)有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能消耗
4)使用多路I/O復(fù)用模型,非阻塞IO
5)使用底層模型不同,它們之間底層實(shí)現(xiàn)方式以及與客戶端之間通信的應(yīng)用協(xié)議不一樣,Redis直接自己構(gòu)建了VM 機(jī)制 ,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會(huì)浪費(fèi)一定的時(shí)間去移動(dòng)和請(qǐng)求
Redis 一級(jí)緩存與二級(jí)緩存(不知道答案對(duì)不對(duì))
緩存為了減輕數(shù)據(jù)庫(kù)訪問(wèn)量;
一級(jí)比二級(jí)多了一級(jí)
一級(jí)緩存請(qǐng)求內(nèi)存,沒(méi)有的話在請(qǐng)求數(shù)據(jù)庫(kù);
二級(jí)緩存請(qǐng)求內(nèi)存,沒(méi)有在請(qǐng)求二級(jí)緩存區(qū),沒(méi)有在請(qǐng)求數(shù)據(jù)庫(kù);
Hibernate 二級(jí)緩存需要添加配置文件
redis 自帶二級(jí)緩存
因?yàn)閿?shù)據(jù)庫(kù)去進(jìn)行IO操作(增刪更新)都需要像(唱片)的刻度一樣,動(dòng)刻度,非常慢,
所以需要緩存減輕數(shù)據(jù)庫(kù)訪問(wèn)量達(dá)到什么減輕數(shù)據(jù)庫(kù)壓力等等作用;
在看看別人的標(biāo)準(zhǔn)答案:
hibernate一級(jí)緩存和二級(jí)緩存的區(qū)別: https://blog.csdn.net/defonds/article/details/2308972
MyBatis緩存分為一級(jí)緩存和二級(jí)緩存:https://blog.csdn.net/u014756827/article/details/52754750
Nginx
比較好的文章(內(nèi)含教程視頻):https://blog.csdn.net/m0_49558851/article/details/107786372
請(qǐng)解釋一下什么是Nginx?
Nginx—Ngine X,是一款免費(fèi)的、自由的、開(kāi)源的、高性能HTTP服務(wù)器和反向代理服務(wù)器;也是一個(gè)IMAP、POP3、SMTP代理服務(wù)器;Nginx以其高性能、穩(wěn)定性、豐富的功能、簡(jiǎn)單的配置和低資源消耗而聞名。
也就是說(shuō)Nginx本身就可以托管網(wǎng)站(類似于Tomcat一樣),進(jìn)行Http服務(wù)處理,也可以作為反向代理服務(wù)器 、負(fù)載均衡器和HTTP緩存。
Nginx 解決了服務(wù)器的C10K(就是在一秒之內(nèi)連接客戶端的數(shù)目為10k即1萬(wàn))問(wèn)題。它的設(shè)計(jì)不像傳統(tǒng)的服務(wù)器那樣使用線程處理請(qǐng)求,而是一個(gè)更加高級(jí)的機(jī)制—事件驅(qū)動(dòng)機(jī)制,是一種異步事件驅(qū)動(dòng)結(jié)構(gòu)。
請(qǐng)列舉Nginx和Apache 之間的不同點(diǎn)
請(qǐng)解釋Nginx如何處理HTTP請(qǐng)求
Nginx 是一個(gè)高性能的 Web 服務(wù)器,能夠同時(shí)處理大量的并發(fā)請(qǐng)求。它結(jié)合多進(jìn)程機(jī)制和異步機(jī)制 ,異步機(jī)制使用的是異步非阻塞方式 ,接下來(lái)就給大家介紹一下 Nginx 的多線程機(jī)制和異步非阻塞機(jī)制 。
1、多進(jìn)程機(jī)制
服務(wù)器每當(dāng)收到一個(gè)客戶端時(shí),就有 服務(wù)器主進(jìn)程 ( master process )生成一個(gè) 子進(jìn)程( worker process )出來(lái)和客戶端建立連接進(jìn)行交互,直到連接斷開(kāi),該子進(jìn)程就結(jié)束了。
使用進(jìn)程的好處是各個(gè)進(jìn)程之間相互獨(dú)立,不需要加鎖,減少了使用鎖對(duì)性能造成影響,同時(shí)降低編程的復(fù)雜度,降低開(kāi)發(fā)成本。其次,采用獨(dú)立的進(jìn)程,可以讓進(jìn)程互相之間不會(huì)影響 ,如果一個(gè)進(jìn)程發(fā)生異常退出時(shí),其它進(jìn)程正常工作, master 進(jìn)程則很快啟動(dòng)新的 worker 進(jìn)程,確保服務(wù)不會(huì)中斷,從而將風(fēng)險(xiǎn)降到最低。
缺點(diǎn)是操作系統(tǒng)生成一個(gè)子進(jìn)程需要進(jìn)行 內(nèi)存復(fù)制等操作,在資源和時(shí)間上會(huì)產(chǎn)生一定的開(kāi)銷。當(dāng)有大量請(qǐng)求時(shí),會(huì)導(dǎo)致系統(tǒng)性能下降 。
2、異步非阻塞機(jī)制
每個(gè)工作進(jìn)程 使用 異步非阻塞方式 ,可以處理 多個(gè)客戶端請(qǐng)求 。
當(dāng)某個(gè) 工作進(jìn)程 接收到客戶端的請(qǐng)求以后,調(diào)用 IO 進(jìn)行處理,如果不能立即得到結(jié)果,就去 處理其他請(qǐng)求 (即為 非阻塞 );而 客戶端
在此期間也 無(wú)需等待響應(yīng) ,可以去處理其他事情(即為 異步 )。
當(dāng) IO 返回時(shí),就會(huì)通知此 工作進(jìn)程 ;該進(jìn)程得到通知,暫時(shí) 掛起 當(dāng)前處理的事務(wù)去 響應(yīng)客戶端請(qǐng)求 。
請(qǐng)列舉Nginx的一些特性
跨平臺(tái):可以在大多數(shù)Unix like 系統(tǒng)編譯運(yùn)行。而且也有Windows的移植版本。
配置異常簡(jiǎn)單:非常的簡(jiǎn)單,易上手。
非阻塞、高并發(fā)連接:數(shù)據(jù)復(fù)制時(shí),磁盤I/O的第一階段是非阻塞的。官方測(cè)試能支持5萬(wàn)并發(fā)連接,實(shí)際生產(chǎn)中能跑2~3萬(wàn)并發(fā)連接數(shù)(得益于Nginx采用了最新的epoll事件處理模型(消息隊(duì)列)。
Nginx代理和后端Web服務(wù)器間無(wú)需長(zhǎng)連接;
Nginx接收用戶請(qǐng)求是異步的,即先將用戶請(qǐng)求全部接收下來(lái),再一次性發(fā)送到后端Web服務(wù)器,極大減輕后端Web服務(wù)器的壓力。
發(fā)送響應(yīng)報(bào)文時(shí),是邊接收來(lái)自后端Web服務(wù)器的數(shù)據(jù),邊發(fā)送給客戶端。
網(wǎng)絡(luò)依賴性低,理論上只要能夠ping通就可以實(shí)施負(fù)載均衡,而且可以有效區(qū)分內(nèi)網(wǎng)、外網(wǎng)流量。
支持內(nèi)置服務(wù)器檢測(cè)。Nginx能夠根據(jù)應(yīng)用服務(wù)器處理頁(yè)面返回的狀態(tài)碼、超時(shí)信息等檢測(cè)服務(wù)器是否出現(xiàn)故障,并及時(shí)返回錯(cuò)誤的請(qǐng)求重新提交到其它節(jié)點(diǎn)上。
此外還有內(nèi)存消耗小、成本低廉(比F5硬件負(fù)載均衡器廉價(jià)太多)、節(jié)省帶寬、穩(wěn)定性高等特點(diǎn)。
簡(jiǎn)述反向代理和正向代理
正向代理:
對(duì)于目標(biāo)服務(wù)器來(lái)講,感受不到真實(shí)的客戶端,與它通信的是代理客戶端,如kexueguge的軟件就是一個(gè)正向代理
舉個(gè)正向代理的例子,我(客戶端)沒(méi)有綠碼出不了門,但是朋友(代理)有,我(客戶端)讓朋友(代理)去超市買瓶水,而對(duì)于超市(服務(wù)器)來(lái)講,他們感知不到我(客戶端)的存在,這就是正向代理。
反向代理:
我們將請(qǐng)求發(fā)送到服務(wù)器,然后服務(wù)器對(duì)我們的請(qǐng)求進(jìn)行轉(zhuǎn)發(fā),我們只需要和代理服務(wù)器進(jìn)行通信就好
舉個(gè)反向代理例子,我(客戶端)讓朋友(代理)去給我買瓶水,并沒(méi)有說(shuō)去哪里買,反正朋友(代理)買回來(lái)了,對(duì)于我(客戶端)來(lái)講,我(客戶端)感知不到超市(服務(wù)器)的存在,這就是反向代理。
使用“反向代理服務(wù)器”的優(yōu)點(diǎn)是什么?
反向代理服務(wù)器可以隱藏源服務(wù)器的存在和特征。它充當(dāng)互聯(lián)網(wǎng)云和web服務(wù)器之間的中間層。這對(duì)于安全方面來(lái)說(shuō)是很好的,特別是當(dāng)您使用web托管服務(wù)時(shí)。
nginx負(fù)載均衡的幾種常用方式
1、輪詢(默認(rèn))
2、weight 權(quán)重
3、ip_hash指令
解決nginx負(fù)載均衡的session共享問(wèn)題
1、不使用session,換用cookie
2、session存在數(shù)據(jù)庫(kù)(MySQL等)中
3、session存在memcache或者redis中
4、nginx中的ip_hash技術(shù)
一些配置
# upstream 節(jié)點(diǎn)群 upstream backend {server backend1.example.com weight=5;server backend2.example.com:8080;server unix:/tmp/backend3;server backup1.example.com:8080 backup;server backup2.example.com:8080 backup; }server { #轉(zhuǎn)發(fā)location / {# 節(jié)點(diǎn)地址proxy_pass http://backend;} }安全性
攻擊
注入攻擊
如何避免 SQL 注入?
使用預(yù)處理 PreparedStatement。
使用正則表達(dá)式過(guò)濾掉字符中的特殊字符。
什么是 XSS 攻擊,如何避免?
XSS 攻擊:即跨站腳本攻擊,它是 Web 程序中常見(jiàn)的漏洞。原理是攻擊者往 Web 頁(yè)面里插入惡意的腳本代碼(css 代碼、Javascript 代碼等),當(dāng)用戶瀏覽該頁(yè)面時(shí),嵌入其中的腳本代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的,如盜取用戶 cookie、破壞頁(yè)面結(jié)構(gòu)、重定向到其他網(wǎng)站等。
預(yù)防 XSS 的核心是必須對(duì)輸入的數(shù)據(jù)做過(guò)濾處理。
設(shè)計(jì)模式
說(shuō)一下你熟悉的設(shè)計(jì)模式?
單例模式
構(gòu)造參數(shù)私有化,外部不能調(diào)用,提供一個(gè)static的接口保證被創(chuàng)建一次
簡(jiǎn)單的懶漢式
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }比較完整的版本(雙重校驗(yàn)鎖+不允許指令重排):
關(guān)鍵詞:
鎖:synchronized
指令重排:volatile
詳細(xì):https://www.runoob.com/design-pattern/singleton-pattern.html
工廠模式
工廠設(shè)計(jì)模式,顧名思義,就是用來(lái)生產(chǎn)對(duì)象的,在java中,萬(wàn)物皆對(duì)象,這些對(duì)象都需要?jiǎng)?chuàng)建,如果創(chuàng)建的時(shí)候直接new該對(duì)象,就會(huì)對(duì)該對(duì)象耦合嚴(yán)重,假如我們要更換對(duì)象,所有new對(duì)象的地方都需要修改一遍,這顯然違背了軟件設(shè)計(jì)的開(kāi)閉原則,如果我們使用工廠來(lái)生產(chǎn)對(duì)象,我們就只和工廠打交道就可以了,徹底和對(duì)象解耦,如果要更換對(duì)象,直接在工廠里更換該對(duì)象即可,達(dá)到了與對(duì)象解耦的目的;所以說(shuō),工廠模式最大的優(yōu)點(diǎn)就是:解耦
觀察者模式
定義了對(duì)象之間的一對(duì)多的依賴,這樣一來(lái),當(dāng)一個(gè)對(duì)象改變時(shí),它的所有的依賴者都會(huì)收到通知并自動(dòng)更新。
外觀模式
提供一個(gè)統(tǒng)一的接口,用來(lái)訪問(wèn)子系統(tǒng)中的一群接口,外觀定義了一個(gè)高層的接口,讓子系統(tǒng)更容易使用。
模版方法模式
定義了一個(gè)算法的骨架,而將一些步驟延遲到子類中,模版方法使得子類可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法的步驟。
狀態(tài)模式:允許對(duì)象在內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來(lái)好像修改了它的類。
tomcat
默認(rèn)線程數(shù)
150
Shiro
談?wù)凷hiro的工作流程
別人的答案:
首先shiro工作流程中又三個(gè)重要的組件,分別是Subject,SecurityManager,以及Realm。
先來(lái)介紹Subject,即為主體也就相當(dāng)于目前操作系統(tǒng)的用戶直觀來(lái)說(shuō)就相當(dāng)于目前登錄的用戶。這里Subject主要是用來(lái)檢測(cè)用戶的登錄,登錄完之后就主要將工作交給SecurityManager來(lái)完成
其次就是SecurityManager主要來(lái)檢測(cè)目前的用戶Subject的一系列的安全操作,比如說(shuō)當(dāng)前用戶所具備的權(quán)限,以及該用戶的角色是哪一層級(jí)的,在用戶執(zhí)行一系列操作的時(shí)候進(jìn)行授權(quán),避免越權(quán)的操作。
之后就是Realm,他主要就是負(fù)責(zé)與數(shù)據(jù)庫(kù)交互,就比如說(shuō)SecurityManager來(lái)檢測(cè)用戶的權(quán)限是,就需要Realm從數(shù)據(jù)庫(kù)中取出該用戶的權(quán)限以及角色信息,之后才能方便SecurityManager來(lái)進(jìn)行授權(quán)的操作。
我自己練習(xí)的項(xiàng)目是這樣的:
啟動(dòng)項(xiàng)目的時(shí)候,首先會(huì) 配置SecurityManager的生命周期處理器,然后注冊(cè)自己寫的授權(quán)和認(rèn)證,配置shiro攔截器,并開(kāi)啟注解功能
登錄的時(shí)候,先判斷該用戶是否生成過(guò)token,來(lái)進(jìn)行保存或者更新token。
發(fā)送請(qǐng)求的時(shí)候,首先會(huì)攔截除option外所有的請(qǐng)求,進(jìn)行token的非空驗(yàn)證,如果token是空的,則返回錯(cuò)誤信息,如果不是空的,則驗(yàn)證token的有效性,如果無(wú)效,則返回錯(cuò)誤信息,有效的話進(jìn)行權(quán)限驗(yàn)證。先給用戶添加角色和權(quán)限(授權(quán))再進(jìn)行驗(yàn)證,無(wú)權(quán)限返回對(duì)應(yīng)異常,有權(quán)限進(jìn)入對(duì)應(yīng)接口
權(quán)限的注解
@RequiresPermissions //例子: @RequiresPermissions({"save"})Linux
拷文件
跳節(jié)點(diǎn)
前端
前端跨域怎么實(shí)現(xiàn)
1.通過(guò)jsonp跨域
2.跨域資源共享(CORS)
3.nodejs中間件代理跨域
4.nginx反向代理中設(shè)置proxy_cookie_domain
vue2生命周期
實(shí)例創(chuàng)建前后
dom元素掛載前后
組件數(shù)據(jù)更新前后
組件卸載前后
vue3生命周期
setup函數(shù)
頁(yè)面掛載前后
數(shù)據(jù)更新前后
卸載前后
頁(yè)面報(bào)錯(cuò)函數(shù)
新增兩個(gè) 廢棄兩個(gè)
總結(jié)
以上是生活随笔為你收集整理的2023 亲自经历面试的初中级java面试题(持续更新)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: html图片取消纵横比,Web中如何实现
- 下一篇: ChatGPT-4震撼发布