JAVA高級(jí)工程師面試題及答案_第1頁(yè)
JAVA高級(jí)工程師面試題及答案_第2頁(yè)
JAVA高級(jí)工程師面試題及答案_第3頁(yè)
JAVA高級(jí)工程師面試題及答案_第4頁(yè)
JAVA高級(jí)工程師面試題及答案_第5頁(yè)
已閱讀5頁(yè),還剩146頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

目錄TOC\o"1-3"\h\u21038一、Java設(shè)計(jì)模式 6528(一)創(chuàng)建型設(shè)計(jì)模式 6131621. 613584二、Spring相關(guān) 69454(一)Spring核心組件 653911.為何使用spring 6273742.核心組件種類及原理 616003.servlet、filter、listener、interceptor區(qū)別 628267(二)SpringBean 853011.如何創(chuàng)建bean并構(gòu)建其關(guān)系網(wǎng) 876532.bean的生命周期 912433.如何解決循環(huán)依賴問(wèn)題?屬性注入和構(gòu)造器注入哪種會(huì)有循環(huán)依賴的問(wèn)題? 1193024.BeanFactory和ApplicationContext有什么區(qū)別? 11299495.Spring框架中bean的作用域?單例bean是線程安全的么? 12125946.Spring如何注入一個(gè)javacollection?如何注入一個(gè)Jperties? 13327157.請(qǐng)解釋springbean的自動(dòng)裝配?請(qǐng)解釋自動(dòng)裝配模式的區(qū)別? 1485168.請(qǐng)解釋@Autowired注解? 1441569.構(gòu)造方法注入和設(shè)值注入的區(qū)別? 15604910.Spring框架中有哪些不同類型事件? 152284011.FileSystemResource和ClassPathResource有何區(qū)別? 162023512.Spring框架中都用到了哪些設(shè)計(jì)模式? 1614328(三)Spring事物傳播機(jī)制 1628528(四)SpringAOP相關(guān) 17158681.AOP實(shí)現(xiàn)原理是什么? 17205912.應(yīng)用場(chǎng)景有哪些? 1818430(五)SpringIOC(依賴倒置)相關(guān) 1864141.IOC如何工作的? 1829016(六)動(dòng)態(tài)代理相關(guān) 19281581.JDK的動(dòng)態(tài)代理和cglib的動(dòng)態(tài)代理各實(shí)現(xiàn)原理 1928591三、線程/并發(fā)編程相關(guān) 2011042(一)線程池 202291.Thread基礎(chǔ)知識(shí) 20190002.Java中的線程池是如何實(shí)現(xiàn)的?創(chuàng)建線程池的幾個(gè)核心構(gòu)造參數(shù)? 2096273.Executors框架的四種線程池及拒絕策略? 21265754.Jdk拒絕策略 22299015.線程池中的線程是怎么創(chuàng)建的?是一開(kāi)始就隨著線程池的啟動(dòng)創(chuàng)建好的嗎? 2284356.既然提到可以通過(guò)配置不同參數(shù)創(chuàng)建出不同的線程池,那么Java中默認(rèn)實(shí)現(xiàn)好的線程池又有哪些呢?請(qǐng)比較它們的異同? 22310577.什么是Java的內(nèi)存模型,Java中各個(gè)線程是怎么彼此看到對(duì)方的變量的? 2359428.請(qǐng)談?wù)剉olatile關(guān)鍵字有什么特點(diǎn),為什么它能保證變量對(duì)所有線程的可見(jiàn)性?是不是就意味著基于volatile變量的運(yùn)算就是并發(fā)安全的? 24205389.請(qǐng)對(duì)比下volatile對(duì)比Synchronized的異同? 24563010.請(qǐng)對(duì)比下ThreadLocal對(duì)比Synchronized的異同? 251419611.如何在Java線程池中提交線程? 252745312.ThreadLocal原理? 253022313.ThreadLocal是怎么解決并發(fā)安全的? 262227714.很多人都說(shuō)要慎用ThreadLocal,談?wù)勀愕睦斫?,使用ThreadLocal需要注意些什么? 27513815.HA主備怎么預(yù)防腦裂? 2720623(二)Synchronized 27178791.Synchronized其原理是什么? 2753002.什么是可重入性,為什么說(shuō)Synchronized是可重入鎖? 27202743.跟Synchronized相比,可重入鎖ReentrantLock其實(shí)現(xiàn)原理有什么不同? 28207094.請(qǐng)談?wù)凴eentrantReadWriteLock和StampedLock? 2812745.那么請(qǐng)談?wù)凙QS框架是怎么回事兒? 2859196.JVM對(duì)Java的原生鎖做了哪些優(yōu)化? 2919647.為什么說(shuō)Synchronized是一個(gè)悲觀鎖?樂(lè)觀鎖的實(shí)現(xiàn)原理又是什么?什么是CAS,它有什么特性? 30272678.如何讓Java的線程彼此同步?你了解過(guò)哪些同步器?請(qǐng)分別介紹下? 3026679四、集合相關(guān) 3029026(一)集合在哪幾個(gè)包下 3012350(二)Map接口 312611.Map接口的實(shí)現(xiàn)有哪些,區(qū)別是什么? 31208142.為什map沒(méi)有實(shí)現(xiàn)collection接口 3162763.為什么collection沒(méi)有實(shí)現(xiàn)clonable和Serializable接口? 31232594.Collection和Collections的區(qū)別? 31192915.Comparable和Comparator接口是干什么的?列出它們的區(qū)別 ? 315373(三)紅黑樹(shù)的概念 3224994(四)HashMap 32200381.HashMap數(shù)據(jù)結(jié)構(gòu)?工作原理及其特點(diǎn) 32253632.HashMaphash沖突如何解決(鏈表和紅黑樹(shù)),為什么hashmap中的鏈表需要轉(zhuǎn)成紅黑樹(shù)? 33238543.HashMaphash什么時(shí)候擴(kuò)容?擴(kuò)容時(shí)每個(gè)entry需要再計(jì)算一次hash嗎?擴(kuò)容時(shí)避免rehash的優(yōu)化 34110814.Hashmap的數(shù)組長(zhǎng)度為什么要保證是2的冪? 3466245.HashMap和Hashtable的區(qū)別? 3522742(五)LinkedHashMap 35315991.LinkedHashMap了解基本原理、哪兩種有序、如何用它實(shí)現(xiàn)LRU? 3513859(六)TreeMap 3671031.TreeMap的據(jù)結(jié)構(gòu) 3629238(七)Set(繼承Collection) 36162901.HashSet的底層實(shí)現(xiàn)是什么? 36288862.HashSet和TreeSet有什么區(qū)別? 36115193.Set里的元素是不能重復(fù)的,那么用什么方法來(lái)區(qū)分重復(fù)與否呢?是用==還是equals()?它們有何區(qū)別? 3729863(八)List(繼承Collection) 3799741.List的實(shí)現(xiàn)有哪些?區(qū)別是什么? 37151452.?dāng)?shù)組(Array)和列表(ArrayList)有什么區(qū)別?什么時(shí)候應(yīng)該使用Array而不是ArrayList? 37267173.什么是迭代器(Iterator)?Iterator和ListIterator的區(qū)別是什么? 388650五、虛擬機(jī)相關(guān) 3830486(一)堆和棧 38257051.heap和stack有什么區(qū)別 3816129虛擬機(jī)棧 39186742.JVM內(nèi)存模型 3965603.Jvm編譯和執(zhí)行的過(guò)程 39268914.什么是類加載器?Java類加載過(guò)程?描述一下JVM加載Class文件的原理機(jī)制? 40203805.類加載器雙親委派模型機(jī)制? 4145776.內(nèi)存管理 42194167.垃圾回收 43132028.JVM的永久代中會(huì)發(fā)生垃圾回收么? 44132359.Java8移除永久代原因? 442581010.OutOfMemory解決方案 443036611.虛擬機(jī)棧什么情況下會(huì)stackoverflowEorror 442577912.如何判斷一個(gè)對(duì)象是否存活?(或者GC對(duì)象的判定方法) 451413913.finalize()方法什么時(shí)候被調(diào)用?析構(gòu)函數(shù)(finalization)的目的是什么? 45505314.如果對(duì)象的引用被置為null,垃圾收集器是否會(huì)立即釋放對(duì)象占用的內(nèi)存? 451705315.什么是分布式垃圾回收(DGC)?它是如何工作的? 452629516.串行(serial)收集器和吞吐量(throughput)收集器的區(qū)別是什么? 4611877六、網(wǎng)絡(luò)相關(guān) 4610454(一)Tcp/IP 46155581.TCP/IP原理?TCP三次握手/四次握手? 46205142.Http原理? 48239953.Httppost/get區(qū)別? 48323424.CDN原理? 487933七、NoSql及緩存相關(guān) 4922930(一)Redis緩存 49103481.Redis原理及應(yīng)用場(chǎng)景?支持的數(shù)據(jù)類型? 498952.Redis持久化的方式 5043693.Redis的哈希設(shè)計(jì)原理?哈希的Rehash是怎么處理的? 50273694.說(shuō)說(shuō)Redis哈希槽的概念? 51309485.為什么每個(gè)字典中包含兩個(gè)hashtable? 51212106.與HashMap的擴(kuò)容對(duì)比? 51301947.redis性能為什么高? 529428.單線程的redis如何利用多核cpu機(jī)器/如何處理那么多的并發(fā)客戶端連接? 5260489.redis的緩存淘汰策略? 523219610.redis集群有哪幾種形式?數(shù)據(jù)分片模型? 53643011.有海量key和value都比較小的數(shù)據(jù),在redis中如何存儲(chǔ)才更省內(nèi)存? 5468912.如何保證redis和DB中的數(shù)據(jù)一致性? 542566513.如何解決緩存穿透和緩存雪崩? 551258414.Redis鎖?如何用redis實(shí)現(xiàn)分布式鎖? 552057315.Redis回收策略? 56433416.Redis常見(jiàn)性能問(wèn)題和解決方案? 56943917.MySQL里有2000w數(shù)據(jù),redis中只存20w的數(shù)據(jù),如何保證redis中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)? 57603018.假如Redis里面有1億個(gè)key,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開(kāi)頭的,如果將它們?nèi)空页鰜?lái)? 572603019.使用過(guò)Redis做異步隊(duì)列么,你是怎么用的? 571323620.Redis主從復(fù)制? 572447921.Redis的高可用部署方式? 58725322.Redis可以在線擴(kuò)容嗎?zk呢? 5823937(二)Memcached緩存 58189511.Memcached原理及應(yīng)用場(chǎng)景? 58293202.如何實(shí)現(xiàn)分布式? 59297563.Memcache的惰性失效機(jī)制? 59279424.memcache緩存的無(wú)底洞現(xiàn)象? 60310425.Memcache服務(wù)集群實(shí)現(xiàn)? 60239546.一致性hash算法的實(shí)現(xiàn)原理? 6038807.Memcached/redis區(qū)別及優(yōu)缺點(diǎn)? 6013702(三)Ehcache\caffeine\jetcache緩存 61197131.cache種類 61294402.Ehcache緩存 61223053.Jetcache緩存 6256494.Caffeine緩存 623645八、Dubbo相關(guān) 6325072(一)Dubbo功能 63247331.了解一個(gè)常用的RPC框架 63112552.為什么要用dubbo? 6355613.Dubbo的整體架構(gòu)設(shè)計(jì)有哪些分層? 63202734.Dubbo如何做負(fù)載均衡? 63286735.服務(wù)調(diào)用時(shí)阻塞的嗎? 63208916.默認(rèn)使用什么序列化框架?你知道的還有哪些? 6375817.Dubbo如何做限流降級(jí)? 63287568.Dubbo如何優(yōu)雅的下線服務(wù)? 63308219.服務(wù)提供者能實(shí)現(xiàn)失效踢出是什么原理? 641286910.如何解決服務(wù)調(diào)用鏈過(guò)長(zhǎng)的問(wèn)題? 642211311.Dubbo如何實(shí)現(xiàn)異步調(diào)用的? 642381412.Dubbo如何實(shí)現(xiàn)失敗重試的? 643061513.Dubbo集群容錯(cuò)有幾種方案? 641794214.同一個(gè)服務(wù)多個(gè)注冊(cè)的情況下可以直連某一個(gè)服務(wù)嗎? 641713315.Dubbo使用過(guò)程中都遇到什么問(wèn)題? 64271716.DubboMonitor實(shí)現(xiàn)原理? 6421347九、RocketMq/Kafka相關(guān) 6519010(一)RocketMq功能 6581911.RocketMq如何保證高可用的? 6597122.RocketMq如何保證高吞吐的? 6571863.RocketMq的消息是有序的嗎? 6524254.RocketMq的消息局部順序是如何保證的? 65232445.RocketMq事務(wù)消息的實(shí)現(xiàn)機(jī)制? 65162366.RocketMq會(huì)有重復(fù)消費(fèi)的問(wèn)題嗎?如何解決? 65225777.RocketMq支持什么級(jí)別的延遲消息?如何實(shí)現(xiàn)的? 6522148.RocketMq是推模型還是拉模型? 65232749.Consumer的負(fù)載均衡是怎么樣的? 6532100(二)Kafka功能 66157641.Kafka數(shù)據(jù)存儲(chǔ)設(shè)計(jì)? 66276122.生產(chǎn)者設(shè)計(jì)? 6690693.消費(fèi)者設(shè)計(jì)? 6618601十、zookeeper相關(guān) 6731642(一)原理 67101251.Zk大致原理(可以了解下原理相近的Raft算法)? 6739212.如何用zk實(shí)現(xiàn)分布式鎖,與redis分布式鎖有和優(yōu)缺點(diǎn)? 67100753.哪四種類型znode? 67314094.Zk通知機(jī)制? 67209905.ZK是如何保證事物的順序一致性的? 68115446.Zk節(jié)點(diǎn)宕機(jī)如何處理? 68148467.ZK負(fù)載均衡和nginx負(fù)載均衡區(qū)別? 68135978.ZKwatch機(jī)制? 68104879.Zk是如何選取主leader的? 6832179十一、MySql相關(guān) 683792(一)存儲(chǔ)引擎 6833181.InnoDB和MyISAM存儲(chǔ)引擎的區(qū)別? 688127(二)Mysql索引 6968221.索引、聚簇索引和非聚簇索引、Btree/hash區(qū)別 69162182.說(shuō)說(shuō)什么是最左匹配? 69172643.如何優(yōu)化慢查詢? 692376(三)數(shù)據(jù)庫(kù)事物 6918961.事物隔離級(jí)別有哪些?不同事務(wù)隔離級(jí)別分別會(huì)加哪些鎖? 6931422.什么是MVCC 70300483.鎖機(jī)制?mysql的行鎖、表鎖、間隙鎖、意向鎖分別是做什么的? 71129664.分布式事務(wù)模型之XA和TCC的區(qū)別和聯(lián)系? 7112808(四)分庫(kù)分表相關(guān) 72275041.分庫(kù)分表如何選擇分表鍵? 72166352.分庫(kù)分表的情況下,查詢時(shí)一般是如何做排序的? 724533.?dāng)?shù)據(jù)庫(kù)主從復(fù)制? 72Spring相關(guān)Spring核心組件為何使用spring輕量、控制反轉(zhuǎn)IOC、面向切面AOP、容器(包含并管理應(yīng)用對(duì)象的配置和生命周期)、MVC。核心組件種類及原理Spring的核心組件有Context、Core、Bean,其中Bean是spring的核心中的核心,如IOC,沒(méi)有Bean也就無(wú)從IOC了。核心組件詳解把bean比作演員的話,Context就好比如舞臺(tái),Core猶如道具。Bean:對(duì)Bean的解析實(shí)際上就是對(duì)spring配置文件進(jìn)行解析,當(dāng)spring成功解析你定義的一個(gè)<bean/>節(jié)點(diǎn)后,在spring的內(nèi)部它就被轉(zhuǎn)化成BeanDefinition對(duì)象,以后所有的操作都是對(duì)這個(gè)對(duì)象進(jìn)行的。Context:發(fā)現(xiàn)每個(gè)Bean之間的關(guān)系,為它們建立這種關(guān)系并維護(hù)好這種關(guān)系,所以Context就是一個(gè)個(gè)Bean的關(guān)系集合,這個(gè)關(guān)系集合又叫Ioc容器。Core:發(fā)現(xiàn)、建立和維護(hù)每個(gè)Bean之間關(guān)系所需要的一系列工具,可以比作成Util(如序列化、注解、解析xml所需工具)。servlet、filter、listener、interceptor區(qū)別1、servletservlet是一種運(yùn)行服務(wù)器端的java應(yīng)用程序,Servlet的主要功能 在于交互式地瀏覽和修改數(shù)據(jù),生成動(dòng)態(tài)Web內(nèi)容。這個(gè)過(guò)程為:1)客戶端發(fā)送請(qǐng)求至服務(wù)器端;2)服務(wù)器將請(qǐng)求信息發(fā)送至Servlet;3)Servlet生成響應(yīng)內(nèi)容并將其傳給服務(wù)器。響應(yīng)內(nèi)容動(dòng)態(tài)生成,通常取 決于客戶端的請(qǐng)求;4)服務(wù)器將響應(yīng)返回給客戶端。在Web應(yīng)用程序中,一個(gè)Servlet在一個(gè)時(shí)刻可能被多個(gè)用戶同時(shí)訪問(wèn)。這時(shí)Web容器將為每個(gè)用戶創(chuàng)建一個(gè)線程來(lái)執(zhí)行Servlet。如果Servlet不涉及共享資源的問(wèn)題,不必關(guān)心多線程問(wèn)題。但如果Servlet需要共享資源,需要保證Servlet是線程安全的。2、filterFilter不像Servlet,它不能產(chǎn)生一個(gè)請(qǐng)求或者響應(yīng),它只是修改對(duì) 某一資源的請(qǐng)求,或者修改從某一的響應(yīng)。Servlet中的過(guò)濾器Filter是實(shí) 現(xiàn)了javax.servlet.Filter接口的服務(wù)器端程序,主要的用途是過(guò)濾字符 編碼、做一些業(yè)務(wù)邏輯判斷等。其工作原理是,只要你在web.xml文件配置 好要攔截的客戶端請(qǐng)求,它都會(huì)幫你攔截到請(qǐng)求,此時(shí)你就可以對(duì)請(qǐng)求或響 應(yīng)(Request、Response)統(tǒng)一設(shè)置編碼,簡(jiǎn)化操作;同時(shí)還可進(jìn)行邏輯判斷, 如用戶是否已經(jīng)登陸、有沒(méi)有權(quán)限訪問(wèn)該頁(yè)面等等工作。它是隨你的web應(yīng) 用啟動(dòng)而啟動(dòng)的,只初始化一次,以后就可以攔截相關(guān)請(qǐng)求,只有當(dāng)你的web 應(yīng)用停止或重新部署的時(shí)候才銷毀。Filter有如下幾個(gè)用處:在HttpServletRequest到達(dá)Servlet之前,攔截客戶的 HttpServletRequest。根據(jù)需要檢查HttpServletRequest,也可以修改HttpServletRequest頭和 數(shù)據(jù)。在HttpServletResponse到達(dá)客戶端之前,攔截HttpServletResponse。根據(jù)需要檢查HttpServletResponse,也可以修改HttpServletResponse頭 和數(shù)據(jù)。3、listenerservlet,filter都是針對(duì)url之類的,而listener是針對(duì)對(duì)象的操 作的,如session的創(chuàng)建,session.setAttribute的發(fā)生,在這樣的事件發(fā) 生時(shí)做一些事情。4、interceptor是在面向切面編程的,就是在你的service或者一個(gè)方法,前調(diào)用一 個(gè)方法,或者在方法后調(diào)用一個(gè)方法,是基于JAVA的反射機(jī)制。比如動(dòng)態(tài) 代理就是攔截器的簡(jiǎn)單實(shí)現(xiàn),在你調(diào)用方法前打印出字符串(或者做其它業(yè) 務(wù)邏輯的操作),也可以在你調(diào)用方法后打印出字符串,甚至在你拋出異常 的時(shí)候做業(yè)務(wù)邏輯的操作。filter配置在web.xml中,任何url都會(huì)攔截,至于怎么處理由開(kāi)發(fā)者 決定,一般用于驗(yàn)證是否登錄,interceptor配置在action中,只會(huì)對(duì)一個(gè)或 者某幾個(gè)action起作用,不會(huì)對(duì)url起作用,一般用于功能方面的驗(yàn)證,是否 有某些權(quán)限的驗(yàn)證等servlet、filter、listener是配置到web.xml中(web.xml的加載順序是:context-param->listener->servlet->filter),interceptor不配置到web.xml中,struts的攔截器配置到struts.xml中。spring的攔截器配置到spring.xml中。SpringBean先理解兩個(gè)概念:實(shí)例化實(shí)例化的過(guò)程是一個(gè)創(chuàng)建Bean的過(guò)程,即調(diào)用Bean的構(gòu)造函數(shù),單例的Bean 放入單例池中。初始化初始化的過(guò)程是一個(gè)賦值的過(guò)程,即調(diào)用Bean的setter,設(shè)置Bean的屬性。如何創(chuàng)建bean并構(gòu)建其關(guān)系網(wǎng)bean的實(shí)例化是在BeanFactory中發(fā)生的首先ApplicationContext繼承ResourceLoader獲取所有資源文件,然后創(chuàng)建beanFactory,創(chuàng)建bean的流程如下:注:、FactoryBean:它是一個(gè)非常重要的bean,如果一個(gè)類繼承該類,則用戶可以自定義產(chǎn)生實(shí)例的方法,只需實(shí)現(xiàn)它的getObject()方法即可bean的生命周期SpringBean的生命周期分為四個(gè)階段和多個(gè)擴(kuò)展點(diǎn)。擴(kuò)展點(diǎn)又可以分為影響多個(gè)Bean和影響單個(gè)Bean。整理如下:

四個(gè)階段實(shí)例化Instantiation屬性賦值Populate初始化Initialization銷毀Destruction多個(gè)擴(kuò)展點(diǎn)影響多個(gè)BeanBeanPostProcessor(解析bean的注解、將注解中的字段轉(zhuǎn)化為屬性、打印日志、記錄時(shí)間、緩存技術(shù)等)影響單個(gè)BeanAwareAwareGroup1BeanNameAwareBeanClassLoaderAwareBeanFactoryAwareAwareGroup2EnvironmentAwareEmbeddedValueResolverAwareApplicationContextAware(ResourceLoaderAware\ApplicationEventPublisherAware\MessageSourceAware)生命周期InitializingBeanDisposableBean先區(qū)別一下SpringBean的實(shí)例化和初始化兩個(gè)階段的主要作用:實(shí)例化:實(shí)例化的過(guò)程是一個(gè)創(chuàng)建Bean的過(guò)程,即調(diào)用Bean的構(gòu)造函數(shù),單例的Bean放入單例池中(父類的類構(gòu)造器<clinit>()->子類的類構(gòu)造器<clinit>()->父類的成員變量和實(shí)例代碼塊->父類的構(gòu)造函數(shù)->子類的成員變量和實(shí)例代碼塊->子類的構(gòu)造函數(shù))。初始化:初始化的過(guò)程是一個(gè)賦值的過(guò)程,即調(diào)用Bean的setter,設(shè)置Bean的屬性。1、實(shí)例化一個(gè)Bean2、按照Spring上下文對(duì)實(shí)例化的Bean進(jìn)行配置,也就是IOC注入3、如果這個(gè)Bean已經(jīng)實(shí)現(xiàn)了BeanNameAware接口,會(huì)調(diào)用它實(shí)現(xiàn)的setBeanName(String)方法,傳遞的參數(shù)就是Spring配置文件中Bean的id值4、如果這個(gè)Bean已經(jīng)實(shí)現(xiàn)了BeanFactoryAware接口,會(huì)調(diào)用它實(shí)現(xiàn)的setBeanFactory(BeanFactory),傳遞的是Spring工廠自身5、如果這個(gè)Bean已經(jīng)實(shí)現(xiàn)了ApplicationContextAware接口,會(huì)調(diào)用setApplicationContext(ApplicationContext)方法,傳入Spring上下文6、如果這個(gè)Bean關(guān)聯(lián)了BeanPostProcessor接口,將會(huì)調(diào)用postProcessBeforeInitialization(Objectobj,Strings)方法,BeanPostProcessor經(jīng)常被用作是Bean內(nèi)容的更改,并且由于這個(gè)是在Bean初始化結(jié)束時(shí)調(diào)用那個(gè)的方法,也可以被應(yīng)用于內(nèi)存或緩存技術(shù);7、如果Bean在Spring配置文件中配置了init-method屬性會(huì)自動(dòng)調(diào)用其配置的初始化方法。8、如果這個(gè)Bean關(guān)聯(lián)了BeanPostProcessor接口,將會(huì)調(diào)用postProcessAfterInitialization(Objectobj,Strings)方法9、當(dāng)Bean不再需要時(shí),會(huì)經(jīng)過(guò)清理階段,如果Bean實(shí)現(xiàn)了DisposableBean這個(gè)接口,會(huì)調(diào)用那個(gè)其實(shí)現(xiàn)的destroy()方法;10、最后,如果這個(gè)Bean的Spring配置中配置了destroy-method屬性,會(huì)自動(dòng)調(diào)用其配置的銷毀方法。如何解決循環(huán)依賴問(wèn)題?屬性注入和構(gòu)造器注入哪種會(huì)有循環(huán)依賴的問(wèn)題?答:構(gòu)造器注入會(huì)有循環(huán)依賴問(wèn)題產(chǎn)生原因:A是單例(構(gòu)造器注入屬性),B是原型然后循環(huán)依賴?答案是不可以注入:A創(chuàng)建的時(shí)候,不會(huì)暴露出來(lái),B就更不會(huì)暴露出來(lái)了,所以拋異常(2)A是單例(構(gòu)造器注入),B是單例(setter方法注入)然后循環(huán)依賴呢?答案是看實(shí)例化的順序:如果A先實(shí)例化:A構(gòu)造器注入,構(gòu)造的時(shí)候就找B,B沒(méi)有實(shí)例化,然后實(shí)例化B,無(wú)參構(gòu)造方法實(shí)例化B,然后將B暴露出來(lái),接著注入A,此時(shí)就發(fā)現(xiàn)A已經(jīng)在實(shí)例化了,又實(shí)例化,所以報(bào)錯(cuò) 如果B先實(shí)例化:B先構(gòu)造然后暴露出來(lái),接著A創(chuàng)建,依賴B,這時(shí)候 能成功的構(gòu)造出來(lái)A(因?yàn)锽已經(jīng)暴露出來(lái)了),接著Asetter注入A--完成 注入解決辦法:初始化bean的時(shí)候(注意此時(shí)的bean必須是單例,否則不能提前暴露一個(gè)創(chuàng)建中的bean)使用set方法進(jìn)行注入屬性,此時(shí)bean對(duì)象會(huì)先執(zhí)行構(gòu)造器實(shí)例化,接著將實(shí)例化后的bean放入一個(gè)map中,并提供引用。當(dāng)需要通過(guò)set方式設(shè)置bean的屬性的時(shí)候,spring容器就會(huì)從map中取出被實(shí)例化的bean。比如A對(duì)象需要set注入B對(duì)象,那么從Map中取出B對(duì)象即可。以此類推,不會(huì)出現(xiàn)循環(huán)依賴的異常。BeanFactory和ApplicationContext有什么區(qū)別?BeanFactory:是Spring里面最低層的接口,提供了最簡(jiǎn)單的容器的功能,只提供了實(shí)例化對(duì)象和拿對(duì)象的功能;BeanFactory在啟動(dòng)的時(shí)候不會(huì)去實(shí)例化Bean,只有從容器中拿Bean的時(shí)候才會(huì)去實(shí)例化。ApplicationContext:應(yīng)用上下文,繼承BeanFactory接口,它是Spring的一各更高級(jí)的容器,提供了更多的有用的功能;1)國(guó)際化(MessageSource)2)訪問(wèn)資源,如URL和文件(ResourceLoader)3)載入多個(gè)(有繼承關(guān)系)上下文,使得每一個(gè)上下文都專注于一個(gè)特定的層次,比如應(yīng)用的web層4)消息發(fā)送、響應(yīng)機(jī)制(ApplicationEventPublisher)5)AOP(攔截器)ApplicationContext在啟動(dòng)的時(shí)候就把所有的Bean全部實(shí)例化了。它還可以為Bean配置lazy-init=true來(lái)讓Bean延遲實(shí)例化。其他:Spring框架中bean的作用域?單例bean是線程安全的么?作用域:Spring的bean作用域(scope)類型1、singleton:單例,默認(rèn)作用域。2、prototype:原型,每次創(chuàng)建一個(gè)新對(duì)象。3、request:請(qǐng)求,每次Http請(qǐng)求創(chuàng)建一個(gè)新對(duì)象,適用于WebApplicationContext環(huán)境下。4、session:會(huì)話,同一個(gè)會(huì)話共享一個(gè)實(shí)例,不同會(huì)話使用不用的實(shí)例。5、global-session:全局會(huì)話,所有會(huì)話共享一個(gè)實(shí)例。Bean線程安全問(wèn)題:原型Bean:對(duì)于原型Bean,每次創(chuàng)建一個(gè)新對(duì)象,也就是線程之間并不存在Bean共享,自然是不會(huì)有線程安全的問(wèn)題。單例Bean:對(duì)于單例Bean,所有線程都共享一個(gè)單例實(shí)例Bean,因此是存在資源的競(jìng)爭(zhēng)。如果單例Bean,是一個(gè)無(wú)狀態(tài)Bean,也就是線程中的操作不會(huì)對(duì)Bean的成員執(zhí)行查詢以外的操作,那么這個(gè)單例Bean是線程安全的。比如Springmvc的Controller、Service、Dao等,這些Bean大多是無(wú)狀態(tài)的,只關(guān)注于方法本身。有狀態(tài)對(duì)象(StatefulBean):就是有實(shí)例變量的對(duì)象,可以保存數(shù)據(jù),是非線程安全的。每個(gè)用戶有自己特有的一個(gè)實(shí)例,在用戶的生存期內(nèi),bean保持了用戶的信息,即“有狀態(tài)”;一旦用戶滅亡(調(diào)用結(jié)束或?qū)嵗Y(jié)束),bean的生命期也告結(jié)束。即每個(gè)用戶最初都會(huì)得到一個(gè)初始的bean。無(wú)狀態(tài)對(duì)象(StatelessBean):就是沒(méi)有實(shí)例變量的對(duì)象,不能保存數(shù)據(jù),是不變類,是線程安全的。bean一旦實(shí)例化就被加進(jìn)會(huì)話池中,各個(gè)用戶都可以共用。即使用戶已經(jīng)消亡,bean的生命期也不一定結(jié)束,它可能依然存在于會(huì)話池中,供其他用戶調(diào)用。由于沒(méi)有特定的用戶,那么也就不能保持某一用戶的狀態(tài),所以叫無(wú)狀態(tài)bean。但無(wú)狀態(tài)會(huì)話bean并非沒(méi)有狀態(tài),如果它有自己的屬性(變量),那么這些變量就會(huì)受到所有調(diào)用它的用戶的影響,這是在實(shí)際應(yīng)用中必須注意的。對(duì)于有狀態(tài)的bean,Spring官方提供的bean,一般提供了通過(guò)ThreadLocal去解決線程安全的方法,比如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等。使用ThreadLocal的好處:使得多線程場(chǎng)景下,多個(gè)線程對(duì)這個(gè)單例Bean的成員變量并不存在資源的競(jìng)爭(zhēng),因?yàn)門(mén)hreadLocal為每個(gè)線程保存線程私有的數(shù)據(jù)。這是一種以空間換時(shí)間的方式。Spring如何注入一個(gè)javacollection?如何注入一個(gè)Jperties?Spring提供了以下四種集合類的配置元素:<list>:該標(biāo)簽用來(lái)裝配可重復(fù)的list值。<set>:該標(biāo)簽用來(lái)裝配沒(méi)有重復(fù)的set值。<map>:該標(biāo)簽可用來(lái)注入鍵和值可以為任何類型的鍵值對(duì)。<props>:該標(biāo)簽支持注入鍵和值都是字符串類型的鍵值對(duì)。請(qǐng)解釋springbean的自動(dòng)裝配?請(qǐng)解釋自動(dòng)裝配模式的區(qū)別?解釋:在配置文件中設(shè)定bean的依賴關(guān)系是一個(gè)很好的機(jī)制,Spring容器還可以自動(dòng)裝配合作關(guān)系bean之間的關(guān)聯(lián)關(guān)系。這意味著Spring可以通過(guò)向BeanFactory中注入的方式自動(dòng)搞定bean之間的依賴關(guān)系。自動(dòng)裝配可以設(shè)置在每個(gè)bean上,也可以設(shè)定在特定的bean上。可以使用@Autowired注解形式,也可以在<beanautowire="byName"/>達(dá)到同樣效果。模式區(qū)別:no:這是Spring框架的默認(rèn)設(shè)置,在該設(shè)置下自動(dòng)裝配是關(guān)閉的,開(kāi)發(fā)者需要自行在bean定義中用標(biāo)簽明確的設(shè)置依賴關(guān)系。byName:該選項(xiàng)可以根據(jù)bean名稱設(shè)置依賴關(guān)系。當(dāng)向一個(gè)bean中自動(dòng)裝配一個(gè)屬性時(shí),容器將根據(jù)bean的名稱自動(dòng)在在配置文件中查詢一個(gè)匹配的bean。如果找到的話,就裝配這個(gè)屬性,如果沒(méi)找到的話就報(bào)錯(cuò)。byType:該選項(xiàng)可以根據(jù)bean類型設(shè)置依賴關(guān)系。當(dāng)向一個(gè)bean中自動(dòng)裝配一個(gè)屬性時(shí),容器將根據(jù)bean的類型自動(dòng)在在配置文件中查詢一個(gè)匹配的bean。如果找到的話,就裝配這個(gè)屬性,如果沒(méi)找到的話就報(bào)錯(cuò)。constructor:造器的自動(dòng)裝配和byType模式類似,但是僅僅適用于與有構(gòu)造器相同參數(shù)的bean,如果在容器中沒(méi)有找到與構(gòu)造器參數(shù)類型一致的bean,那么將會(huì)拋出異常。autodetect:該模式自動(dòng)探測(cè)使用構(gòu)造器自動(dòng)裝配或者byType自動(dòng)裝配。首先會(huì)嘗試找合適的帶參數(shù)的構(gòu)造器,如果找到的話就是用構(gòu)造器自動(dòng)裝配,如果在bean內(nèi)部沒(méi)有找到相應(yīng)的構(gòu)造器或者是無(wú)參構(gòu)造器,容器就會(huì)自動(dòng)選擇byTpe的自動(dòng)裝配方式。請(qǐng)解釋@Autowired注解?答:@Autowired采取的策略為按照類型注入@Resource注解由J2EE提供,需要導(dǎo)入包javax.annotation.Resource。@Resource默認(rèn)按照ByName自動(dòng)注入。構(gòu)造方法注入和設(shè)值注入的區(qū)別?1.在設(shè)值注入方法支持大部分的依賴注入,如果我們僅需要注入int、string和long型的變量,我們不要用設(shè)值的方法注入。對(duì)于基本類型,如果我們沒(méi)有注入的話,可以為基本類型設(shè)置默認(rèn)值。在構(gòu)造方法注入不支持大部分的依賴注入,因?yàn)樵谡{(diào)用構(gòu)造方法中必須傳入正確的構(gòu)造參數(shù),否則的話為報(bào)錯(cuò)。2.設(shè)值注入不會(huì)重寫(xiě)構(gòu)造方法的值。如果我們對(duì)同一個(gè)變量同時(shí)使用了構(gòu)造方法注入又使用了設(shè)置方法注入的話,那么構(gòu)造方法將不能覆蓋由設(shè)值方法注入的值。很明顯,因?yàn)闃?gòu)造方法盡在對(duì)象被創(chuàng)建時(shí)調(diào)用。3.在使用設(shè)值注入時(shí)有可能還不能保證某種依賴是否已經(jīng)被注入,也就是說(shuō)這時(shí)對(duì)象的依賴關(guān)系有可能是不完整的。而在另一種情況下,構(gòu)造器注入則不允許生成依賴關(guān)系不完整的對(duì)象。4.在構(gòu)造方法注入時(shí)如果對(duì)象A和對(duì)象B互相依賴,在創(chuàng)建對(duì)象A時(shí)Spring會(huì)拋出ObjectCurrentlyInCreationException異常,因?yàn)樵贐對(duì)象被創(chuàng)建之前A對(duì)象是不能被創(chuàng)建的,反之亦然。所以Spring用設(shè)值注入的方法解決了循環(huán)依賴的問(wèn)題,因?qū)ο蟮脑O(shè)值方法是在對(duì)象被創(chuàng)建之前被調(diào)用的。Spring框架中有哪些不同類型事件?Spring提供了以下5中標(biāo)準(zhǔn)的事件:上下文更新事件ContextRefreshedEvent:該事件會(huì)在ApplicationContext被初始化或者更新時(shí)發(fā)布。也可以在調(diào)用ConfigurableApplicationContext接口中的refresh()方法時(shí)被觸發(fā)。上下文開(kāi)始事件ContextStartedEvent:當(dāng)容器調(diào)用ConfigurableApplicationContext的Start()方法開(kāi)始/重新開(kāi)始容器時(shí)觸發(fā)該事件。上下文停止事件ContextStoppedEvent:當(dāng)容器調(diào)用ConfigurableApplicationContext的Stop()方法停止容器時(shí)觸發(fā)該事件。上下文關(guān)閉事件ContextClosedEvent:當(dāng)ApplicationContext被關(guān)閉時(shí)觸發(fā)該事件。容器被關(guān)閉時(shí),其管理的所有單例Bean都被銷毀。請(qǐng)求處理事件(RequestHandledEvent):在Web應(yīng)用中,當(dāng)一個(gè)http請(qǐng)求(request)結(jié)束觸發(fā)該事件。FileSystemResource和ClassPathResource有何區(qū)別?ClassPathResource類,當(dāng)資源是在項(xiàng)目里的時(shí)候,用這個(gè),相對(duì)路徑的ClassPathResourcebgFile=newClassPathResource(bgPath,this.getClass());FileSystemResource是絕對(duì)路徑的Spring框架中都用到了哪些設(shè)計(jì)模式?(1)工廠模式:BeanFactory就是簡(jiǎn)單工廠模式的體現(xiàn),用來(lái)創(chuàng)建對(duì)象的實(shí)例;(2)單例模式:Bean默認(rèn)為單例模式。(3)代理模式:Spring的AOP功能用到了JDK的動(dòng)態(tài)代理和CGLIB字節(jié)碼生成技術(shù);(4)模板方法:用來(lái)解決代碼重復(fù)的問(wèn)題。比如.RestTemplate,JmsTemplate,JpaTemplate。(5)觀察者模式:定義對(duì)象鍵一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都會(huì)得到通知被制動(dòng)更新,如Spring中l(wèi)istener的實(shí)現(xiàn)--ApplicationListener。Spring事物傳播機(jī)制首先理解幾個(gè)概念:臟讀:(讀取了未提交的新事物,然后被回滾了)不可重復(fù)讀:(讀取了提交的新事物,指更新操作。不可重復(fù)讀是指在對(duì)于數(shù)據(jù)庫(kù)中的某個(gè)數(shù)據(jù),一個(gè)事務(wù)范圍內(nèi)多次查詢卻返回了不同的數(shù)據(jù)值,這是由于在查詢間隔,被另一個(gè)事務(wù)修改并提交了。解決:如果一個(gè)事物在讀的時(shí)候,禁止任何事物寫(xiě)。是不是就解決了。)幻讀:(也是讀取了提交的新事物,指增刪操作),在事務(wù)A多次讀取構(gòu)成中,事務(wù)B對(duì)數(shù)據(jù)進(jìn)行了新增操作,導(dǎo)致事務(wù)A多次讀取的數(shù)據(jù)不一致?;米x和不可重復(fù)讀的區(qū)別在于,不可重復(fù)是針對(duì)記錄的update操作,只要在記錄上加寫(xiě)鎖,就可避免;幻讀是對(duì)記錄的insert操作,要禁止幻讀必須加上全局的寫(xiě)鎖(比如在表上加寫(xiě)鎖)。Spring事務(wù)七個(gè)事務(wù)傳播行為,在TransactionDefinition接口中定義了七個(gè)事務(wù)傳播行為:PROPAGATION_REQUIRED如果存在一個(gè)事務(wù),則支持當(dāng)前事務(wù)。如果沒(méi)有事務(wù)則開(kāi)啟一個(gè)新的事務(wù)。PROPAGATION_SUPPORTS如果存在一個(gè)事務(wù),支持當(dāng)前事務(wù)。如果沒(méi)有事務(wù),則非事務(wù)的執(zhí)行。但是對(duì)于事務(wù)同步的事務(wù)管理器,PROPAGATION_SUPPORTS與不使用事務(wù)有少許不同。PROPAGATION_NOT_SUPPORTED總是非事務(wù)地執(zhí)行,并掛起任何存在的事務(wù)。PROPAGATION_NEVER總是非事務(wù)地執(zhí)行,如果存在一個(gè)活動(dòng)事務(wù),則拋出異常。PROPAGATION_MANDATORY如果已經(jīng)存在一個(gè)事務(wù),支持當(dāng)前事務(wù)。如果沒(méi)有一個(gè)活動(dòng)的事務(wù),則拋出異常。PROPAGATION_REQUIRES_NEW總是開(kāi)啟一個(gè)新的事務(wù)。如果一個(gè)事務(wù)已經(jīng)存在,則將這個(gè)存在的事務(wù)掛起。PROPAGATION_NESTED如果一個(gè)活動(dòng)的事務(wù)存在,則運(yùn)行在一個(gè)嵌套的事務(wù)中.如果沒(méi)有活動(dòng)事務(wù),則按TransactionDefinition.PROPAGATION_REQUIRED屬性執(zhí)行。Spring事務(wù)的五種隔離級(jí)別,在TransactionDefinition接口中定義了五個(gè)不同的事務(wù)隔離級(jí)別:ISOLATION_DEFAULT這是一個(gè)PlatfromTransactionManager默認(rèn)的隔離級(jí)別,使用數(shù)據(jù)庫(kù)默認(rèn)的事務(wù)隔離級(jí)別.另外四個(gè)與JDBC的隔離級(jí)別相對(duì)應(yīng)。ISOLATION_READ_UNCOMMITTED這是事務(wù)最低的隔離級(jí)別,它充許別外一個(gè)事務(wù)可以看到這個(gè)事務(wù)未提交的數(shù)據(jù)。這種隔離級(jí)別會(huì)產(chǎn)生臟讀,不可重復(fù)讀和幻像讀。ISOLATION_READ_COMMITTED保證一個(gè)事務(wù)修改的數(shù)據(jù)提交后才能被另外一個(gè)事務(wù)讀取。另外一個(gè)事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)。這種事務(wù)隔離級(jí)別可以避免臟讀出現(xiàn),但是可能會(huì)出現(xiàn)不可重復(fù)讀和幻像讀。ISOLATION_REPEATABLE_READ這種事務(wù)隔離級(jí)別可以防止臟讀,不可重復(fù)讀。但是可能出現(xiàn)幻像讀。它除了保證一個(gè)事務(wù)不能讀取另一個(gè)事務(wù)未提交的數(shù)據(jù)外,還保證了避免下面的情況產(chǎn)生(不可重復(fù)讀)。對(duì)行加鎖比如版本號(hào)。ISOLATION_SERIALIZABLE這是花費(fèi)最高代價(jià)但是最可靠的事務(wù)隔離級(jí)別。事務(wù)被處理為順序執(zhí)行。除了防止臟讀,不可重復(fù)讀外,還避免了幻像讀。對(duì)表讀寫(xiě)加鎖。SpringAOP相關(guān)AOP實(shí)現(xiàn)原理是什么?AOP基礎(chǔ)知識(shí):切面:攔截器類,其中會(huì)定義切點(diǎn)以及通知切點(diǎn):具體攔截的某個(gè)業(yè)務(wù)點(diǎn)。通知:切面當(dāng)中的方法,聲明通知方法在目標(biāo)業(yè)務(wù)層的執(zhí)行位置,通知類型如下:前置通知:@Before在目標(biāo)業(yè)務(wù)方法執(zhí)行之前執(zhí)行后置通知:@After在目標(biāo)業(yè)務(wù)方法執(zhí)行之后執(zhí)行返回通知:@AfterReturning在目標(biāo)業(yè)務(wù)方法返回結(jié)果之后執(zhí)行異常通知:@AfterThrowing在目標(biāo)業(yè)務(wù)方法拋出異常之后環(huán)繞通知:@Around功能強(qiáng)大,可代替以上四種通知,還可以控制目標(biāo)業(yè)務(wù)方實(shí)現(xiàn)原理(動(dòng)態(tài)代理):我們能在一個(gè)切點(diǎn)之前執(zhí)行一些操作,在一個(gè)切點(diǎn)之后執(zhí)行一些操作,這個(gè)切點(diǎn)就是一個(gè)個(gè)方法。這些方法所在類肯定就是被代理了,在代理過(guò)程中切入了一些其他操作。(1)、Java動(dòng)態(tài)代理:靜態(tài)代理和動(dòng)態(tài)代理的區(qū)別是在于要不要開(kāi)發(fā)者自己定義Proxy類。動(dòng)態(tài)代理不需要自己手動(dòng)寫(xiě)一個(gè)代理類,通過(guò)Proxy動(dòng)態(tài)生成proxyclass,但是它也指定了一個(gè)InvocationHandler的實(shí)現(xiàn)類。。應(yīng)用場(chǎng)景有哪些?攔截器:日志打印、登錄控制、事務(wù)管理、注入緩存SpringIOC(依賴倒置)相關(guān)IOC如何工作的?IOC也就是所謂的依賴注入,即高層需要什么,就尋找對(duì)應(yīng)的低層來(lái)注入。直接的管理通過(guò)IOC容器來(lái)統(tǒng)一管理和維護(hù),解除直接依賴以及自己手動(dòng)創(chuàng)建和管理bean,IoC的理念就是讓別人為你服務(wù)。舉例:找女朋友過(guò)程:我們把需求告訴婚介中心,婚介中心根據(jù)我們需求匹配合適女性,把找到的女性告訴我們,其中婚介中心就是IOC控制器。容器實(shí)際上是Context組件結(jié)合其他兩個(gè)組件共同構(gòu)建的一個(gè)Bean關(guān)系網(wǎng),構(gòu)建入口就在AbstractApplicationContext類的refresh方法中,代碼大致如下:動(dòng)態(tài)代理相關(guān)JDK的動(dòng)態(tài)代理和cglib的動(dòng)態(tài)代理各實(shí)現(xiàn)原理JDK動(dòng)態(tài)代理:JDK動(dòng)態(tài)代理類實(shí)現(xiàn)了InvocationHandler接口,重寫(xiě)的invoke方法。JDK動(dòng)態(tài)代理的基礎(chǔ)是反射機(jī)制(method.invoke(對(duì)象,參數(shù)))Proxy.newProxyInstance()。Cglib動(dòng)態(tài)代理:原理是對(duì)指定的目標(biāo)生成一個(gè)子類,并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),但因?yàn)椴捎玫氖抢^承,所以不能對(duì)final修飾的類進(jìn)行代理。通過(guò)實(shí)現(xiàn)(MethodInterceptor)Java設(shè)計(jì)模式創(chuàng)建型:如何創(chuàng)建對(duì)象工廠方法模式工廠方法模式、抽象工廠模式建造者模式定義:創(chuàng)建復(fù)雜對(duì)象的算法應(yīng)該獨(dú)立于該對(duì)象的組成部分及裝配方式。建造者模式也就是說(shuō)不僅能創(chuàng)建多個(gè)對(duì)象,還能將按照一定順序裝配起來(lái),案例:建造者模式可以用于描述KFC如何創(chuàng)建套餐:套餐是一個(gè)復(fù)雜對(duì)象,它一般包含主食(如漢堡、雞肉卷等)和飲料(如果汁、可樂(lè)等)等組成部分,不同的套餐有不同的組成部分,而KFC的服務(wù)員可以根據(jù)顧客的要求,一步一步裝配這些組成部分,構(gòu)造一份完整的套餐,然后返回給顧客。優(yōu)點(diǎn):與工廠模式的區(qū)別是:建造者模式更加關(guān)注與零件裝配的順序,且工廠模式關(guān)注創(chuàng)建單個(gè)種對(duì)象,建造者模式可以場(chǎng)景多個(gè)對(duì)象。缺點(diǎn):產(chǎn)品必須有共同點(diǎn),限制了使用范圍。如內(nèi)部變化復(fù)雜,會(huì)有很多的建造類,難以維護(hù)。示例:產(chǎn)品product類,里面包含水果、肉等屬性。構(gòu)造接口builder,定義構(gòu)建水果,構(gòu)建肉兩個(gè)方法。套餐=具體建造者GroupBuilderA,實(shí)現(xiàn)builder接口,實(shí)現(xiàn)上面兩個(gè)方法,比如水果是橘子。服務(wù)員=director類,負(fù)責(zé)控制產(chǎn)品對(duì)象的生產(chǎn)過(guò)程和順序。Productproduct=newProduct();BuilderbuilderA=newGrouopBuilderA(product);Directordirector=newDirector(builderA);director.show();原型模式克隆一個(gè)對(duì)象,當(dāng)一個(gè)系統(tǒng)應(yīng)該獨(dú)立于它的產(chǎn)品創(chuàng)建、構(gòu)成和表示。單例模式當(dāng)類只能有一個(gè)實(shí)例,而且始終只有一個(gè)。結(jié)構(gòu)型:如何組合類和對(duì)象以獲得更大結(jié)構(gòu)如何組合類和對(duì)象以獲得更大結(jié)構(gòu),采用繼承機(jī)制來(lái)組合接口和實(shí)現(xiàn)。簡(jiǎn)單例子是多重繼承,結(jié)果子類包含了所有父類性質(zhì)。適配器模式將一個(gè)類的接口,轉(zhuǎn)換成客戶希望的另外一個(gè)接口。將已有類的接口轉(zhuǎn)換成和目標(biāo)接口兼容。源(Adaptee):需要被適配的對(duì)象或類型,相當(dāng)于插頭。適配器(Adapter):連接目標(biāo)和源的中間對(duì)象,相當(dāng)于插頭轉(zhuǎn)換器。目標(biāo)(Target):期待得到的目標(biāo),相當(dāng)于插座。橋接模式(bridge)將抽象部分與它的實(shí)現(xiàn)部分相分離,使它們都可以獨(dú)立地變化。如A抽象類,使用B類繼承A。C/D/F等都可繼承B并可動(dòng)態(tài)變化,與A解耦(將抽象化(Abstraction)與實(shí)現(xiàn)化(Implementation)脫耦,使得二者可以獨(dú)立地變化)。組合模式組合多個(gè)對(duì)象形成樹(shù)形結(jié)構(gòu)形成整體-部分關(guān)系,即實(shí)現(xiàn)類直接繼承抽象類,組合成一個(gè)新的組合。示例:樹(shù)形的文件結(jié)構(gòu),父文件,子文件包含文件夾或者圖片,子文件夾又包含文件和文檔等等。?!,F(xiàn)在要寫(xiě)一個(gè)功能,指定只刪除文件夾。裝飾模式(decorator)動(dòng)態(tài)的給一個(gè)對(duì)象添加一些額外的功能。當(dāng)不能采用生成子類的方法進(jìn)行擴(kuò)充時(shí),可采用該模式動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。示例:假設(shè)有一個(gè)接口Human,一個(gè)接口的實(shí)現(xiàn)類Man。人類Human是可以跑步的,但是不能飛。如果想給人類加上飛翔的翅膀,可以有三種解決方案:修改實(shí)現(xiàn)類Man的方法,但不符合開(kāi)閉原則給實(shí)現(xiàn)類Man添加一個(gè)子類,擴(kuò)展一個(gè)人類可以飛的功能。問(wèn)題在于,如果又想 給人類增加獵豹般奔跑的速度,需要繼續(xù)擴(kuò)展一個(gè)子類。顯然,使用繼承的方式去擴(kuò)展 一個(gè)類的功能,會(huì)增加類的層級(jí),類的臃腫會(huì)加大維護(hù)的成本。使用裝飾模式擴(kuò)展一個(gè)類的功能。好處在于,如果繼承關(guān)系是縱向的,那么裝飾 類 則是某個(gè)類橫向的擴(kuò)展,并不會(huì)影響繼承鏈上的其他類。例如:CextendsB,BextendsA, 如果需要擴(kuò)展B的功能,可以設(shè)計(jì)一個(gè)B的裝飾類,它并不會(huì)影響B(tài)的子類C。如果采 用在B里面增加方法,勢(shì)必會(huì)使B的所有子類結(jié)構(gòu)被改變。代理模式與decorator結(jié)構(gòu)基本一致,但區(qū)別是,decorator可動(dòng)態(tài)的添加或刪除功能。外觀模式(facade)某子系統(tǒng)為外界提供功能服務(wù),但該子系統(tǒng)中存在很多粒度十分小的類,不便被外界系統(tǒng)直接使用,則可新增一個(gè)入口facade,外界通過(guò)該入口訪問(wèn)子系統(tǒng),采用該模式。行為型:關(guān)注系統(tǒng)中對(duì)象之間的相互交互關(guān)注系統(tǒng)中對(duì)象之間的相互交互,研究系統(tǒng)在運(yùn)行時(shí)對(duì)象之間的相互通信和協(xié)作,進(jìn)一步明確對(duì)象的職責(zé)。職責(zé)鏈模式(chainofresponsibility)使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,將這些對(duì)象連成鏈,直至有個(gè)對(duì)象處理為止。如用戶點(diǎn)擊按鈕->接受響應(yīng)->彈出按鈕或者跳轉(zhuǎn)或者等等,肯定有一個(gè)處理該請(qǐng)求。模板方法模式(templatemethod)定義一個(gè)操作中的算法骨架,而將一些步驟延遲到子類中。該模式使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。例子:一個(gè)父類定義了不可變的方法并定義一些可變的抽象方法。子類只需實(shí)現(xiàn)這些可變的方法就可以了。示例:想要泡一杯茶或者一杯咖啡,第一步都是將水煮沸,第二部是加入咖啡或者茶,第三部就是將飲料倒入杯子中,第四部就是加入各種調(diào)味料。其中第一步和第三部都是一樣的,這個(gè)就可以定義在基類,而第二步和第四步就是他們之間的差異就可以在具體的子類中去實(shí)現(xiàn)。觀察者模式(observer)當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。示例:發(fā)布訂閱,共有4個(gè)角色,如下:抽象被觀察者角色:也就是一個(gè)抽象主題,它把所有對(duì)觀察者對(duì)象的引用保存在一個(gè)集 合中,每個(gè)主題都可以有任意數(shù)量的觀察者。抽象主題提供一個(gè)接口,可以增加和刪除 觀察者角色。一般用一個(gè)抽象類和接口來(lái)實(shí)現(xiàn)。抽象觀察者角色:為所有的具體觀察者定義一個(gè)接口,在得到主題通知時(shí)更新自己。具體被觀察者角色:也就是一個(gè)具體的主題,在集體主題的內(nèi)部狀態(tài)改變時(shí),所有登記 過(guò)的觀察者發(fā)出通知。具體觀察者角色:實(shí)現(xiàn)抽象觀察者角色所需要的更新接口,一邊使本身的狀態(tài)與制圖的 狀態(tài)相協(xié)調(diào)。中介模式(mediator)用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互,從而使各對(duì)象不需要顯式地相互引用,使其耦合松散。示例:如同事之間交流,可以通過(guò)一個(gè)中介人進(jìn)行信息傳達(dá),這樣避免了同事之間過(guò)多的直接聯(lián)系,有以下4個(gè)角色:抽象中介者角色(AbstractMediator):定義出同事對(duì)象到中介者對(duì)象的接口,其中主要方法是一個(gè)(或多個(gè))事件方法。具體中介者角色(ConcreteMediator):實(shí)現(xiàn)抽象中介者中所聲明的事件方法。具體中介者直銷所有的具體同事類,并負(fù)責(zé)具體的協(xié)調(diào)各個(gè)同事對(duì)象的交互關(guān)系。抽象同事類角色(AbstractColleague):定義出紅接著到同事對(duì)象的接口。同事對(duì)象只知道中介者,而不知道其余的同事對(duì)象。具體同事類角色(ConcreteColleague):所有的具體同事類均從抽象同事類繼承而來(lái)。實(shí)現(xiàn)自己的業(yè)務(wù),在需要與其他同事通信的時(shí)候,就與持有的中介者通信,中介者會(huì)負(fù)責(zé)與其他的同時(shí)交互。策略模式(strategy)策略模式是對(duì)算法的包裝,是把使用算法的責(zé)任和算法本身分開(kāi)。定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可以相互轉(zhuǎn)化。示例:假設(shè)現(xiàn)在要設(shè)計(jì)一個(gè)販賣(mài)各類書(shū)籍的電子商務(wù)網(wǎng)站的購(gòu)物車系統(tǒng)。一個(gè)最簡(jiǎn)單的情況就是把所有貨品的單價(jià)乘上數(shù)量,但是實(shí)際情況肯定比這要復(fù)雜。比如,本網(wǎng)站可能對(duì)所有的高級(jí)會(huì)員提供每本20%的促銷折扣;對(duì)中級(jí)會(huì)員提供每本10%的促銷折扣;對(duì)初級(jí)會(huì)員沒(méi)有折扣。迭代器模式(iterator)提供一種方法殊勛放一個(gè)聚合對(duì)象各元素,而又不暴露該對(duì)象內(nèi)部表示。在實(shí)例化列表迭代器之前,必須提供待遍歷的列表。解釋器模式(interpreter)給定一個(gè)語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。命令模式(command)將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而使你可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化,請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可撤銷操作。狀態(tài)模式(state)將每一個(gè)條件分支放入一個(gè)獨(dú)立的類中,這樣就可以根據(jù)對(duì)象自身的情況將對(duì)象的狀態(tài)作為一個(gè)對(duì)象,準(zhǔn)許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為。對(duì)象看起來(lái)似乎修改了它的類。線程/并發(fā)編程相關(guān)線程池Thread基礎(chǔ)知識(shí)1、線程的生命周期線程也同樣要經(jīng)歷開(kāi)始(等待)、運(yùn)行、掛起和停止四種不同的狀態(tài)。這四種狀態(tài)都可以通過(guò)Thread類中的方法進(jìn)行控制。線程在建立后并不馬上執(zhí)行run方法中的代碼,而是處于等待狀態(tài)。線程處于等待狀態(tài)時(shí),可以通過(guò)Thread類的方法來(lái)設(shè)置線程不各種屬性,如線程的優(yōu)先級(jí)(setPriority)、線程名(setName)和線程的類型(setDaemon)等。1、wait、suspend、sleep區(qū)別(1)、suspend()方法容易發(fā)生死鎖。調(diào)用suspend()的時(shí)候,目標(biāo)線程會(huì)停下來(lái),但卻仍然持有在這之前獲得的鎖定。此時(shí),其他任何線程都不能訪問(wèn)鎖定的資源,除非被"掛起"的線程恢復(fù)運(yùn)行。對(duì)任何線程來(lái)說(shuō),如果它們想恢復(fù)目標(biāo)線程,同時(shí)又試圖使用任何一個(gè)鎖定的資源,就會(huì)造成死鎖,調(diào)用resume來(lái)釋放(2)、wait()是Object對(duì)象方法,wait()對(duì)此對(duì)象調(diào)用wait方法導(dǎo)致本線程放棄對(duì)象鎖,進(jìn)入等待此對(duì)象的等待鎖定池,只有針對(duì)此對(duì)象發(fā)出notify方法(或notifyAll)后本線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備獲得對(duì)象鎖進(jìn)入運(yùn)行狀態(tài)。notify與notifyAll區(qū)別:voidnotify():喚醒一個(gè)正在等待該對(duì)象的線程。voidnotifyAll():喚醒所有正在等待該對(duì)象的線程。(3)、sleep()此線程暫停執(zhí)行指定時(shí)間,給執(zhí)行機(jī)會(huì)給其他線程,但是監(jiān)控狀態(tài)依然保持,到時(shí)后會(huì)自動(dòng)恢復(fù)。調(diào)用sleep不會(huì)釋放對(duì)象鎖。sleep需放在try{}catch(){}塊中調(diào)用wait方法會(huì)釋放當(dāng)前線程的鎖(其實(shí)線程間的通信是靠對(duì)象來(lái)管理的,所有操作一個(gè)對(duì)象的線程是這個(gè)對(duì)象通過(guò)自己的wait方法來(lái)管理的,就好像這個(gè)對(duì)象是電視機(jī),三個(gè)人是三個(gè)線程,那么電視機(jī)的遙控器就是這個(gè)鎖,假如現(xiàn)在A拿著遙控器,電視機(jī)調(diào)用wait方法,那么A就交出自己的遙控器,由jVM虛擬機(jī)調(diào)度,遙控器該交給誰(shuí)。)【我想到一個(gè)好玩的例子:如果A拿遙控器的期間,他可以用自己的sleep每隔十分鐘調(diào)一次電視臺(tái),而在他調(diào)臺(tái)休息的十分鐘期間,遙控器還在他的手上~】Java中的線程池是如何實(shí)現(xiàn)的?創(chuàng)建線程池的幾個(gè)核心構(gòu)造參數(shù)?線程池:核心是池化技術(shù),如連接池、對(duì)象池,通過(guò)預(yù)先創(chuàng)建好多個(gè)線程,放在池中,這樣可以在需要使用線程的時(shí)候直接獲取,線程執(zhí)行完一個(gè)任務(wù)后,又去執(zhí)行另一個(gè)任務(wù),避免多次重復(fù)創(chuàng)建、銷毀帶來(lái)的開(kāi)銷。創(chuàng)建過(guò)程:本質(zhì)是ExecutorService接口,可以通過(guò)ThreadPoolExecutor構(gòu)造方法創(chuàng)建,也可以Executors提供的幾個(gè)方法來(lái)創(chuàng)建。核心構(gòu)造參數(shù):corePoolSize:核心線程數(shù)量,可以類比正式員工數(shù)量,常駐線程數(shù)量。maximumPoolSize:最大的線程數(shù)量,公司最多雇傭員工數(shù)量。常駐+臨時(shí)線程數(shù)量。workQueue:多余任務(wù)等待隊(duì)列,再多的人都處理不過(guò)來(lái)了,需要等著,在這個(gè)地方等。keepAliveTime:非核心線程空閑時(shí)間,就是外包人員等了多久,如果還沒(méi)有活干,解雇了。threadFactory:創(chuàng)建線程的工廠,在這個(gè)地方可以統(tǒng)一處理創(chuàng)建的線程的屬性。每個(gè)公司對(duì)員工的要求不一樣,恩,在這里設(shè)置員工的屬性。handler:線程池拒絕策略,什么意思呢?就是當(dāng)任務(wù)實(shí)在是太多,人也不夠,需求池也排滿了,還有任務(wù)咋辦?默認(rèn)是不處理,拋出異常告訴任務(wù)提交者,我這忙不過(guò)來(lái)了。總結(jié)所謂線程池本質(zhì)是一個(gè)hashSet。多余的任務(wù)會(huì)放在阻塞隊(duì)列中。只有當(dāng)阻塞隊(duì)列滿了后,才會(huì)觸發(fā)非核心線程的創(chuàng)建。所以非核心線程只是臨時(shí)過(guò)來(lái)打雜的。直到空閑了,然后自己關(guān)閉了。線程池提供了兩個(gè)鉤子(beforeExecute,afterExecute)給我們,我們繼承線程池,在執(zhí)行任務(wù)前后做一些事情。線程池原理關(guān)鍵技術(shù):鎖(lock,cas)、阻塞隊(duì)列、hashSet(資源池)

Executors框架的四種線程池及拒絕策略?共四種:Executors.newFixedThreadPool(60);設(shè)置固定值會(huì)造成高并發(fā)線程排隊(duì)等待空閑線程,尤其是當(dāng)讀取大數(shù)據(jù)量時(shí)線程處理時(shí)間長(zhǎng)而不釋放線程,導(dǎo)致無(wú)法創(chuàng)建新線程??删彺婢€程池Executors.newCachedThreadPool();線程池?zé)o限大,而系統(tǒng)資源(內(nèi)存等)有限,會(huì)導(dǎo)致機(jī)器內(nèi)存溢出OOM。定長(zhǎng)且可定時(shí)、周期線程池Executors.newScheduledThreadPool(5);單線程線程池Executors.newSingledThreadPool();在使用有界隊(duì)列時(shí),若有新的任務(wù)需要執(zhí)行,(1)若線程池實(shí)際線程數(shù)小于corePoolSize,則優(yōu)先創(chuàng)建線程,(2)若大于corePoolSize,則會(huì)將任務(wù)加入隊(duì)列,(3)若隊(duì)列已滿,則在總線程數(shù)不大于maximumPoolSize的前提下,創(chuàng)建新的線程。(4)若線程數(shù)大于maximumPoolSize,則執(zhí)行拒絕策略?;蚱渌远x方式。Jdk拒絕策略(1)AbortPolicy:默認(rèn),直接拋出異常,系統(tǒng)正常工作。(2)DiscardOldestPolicy:丟棄最老的一個(gè)請(qǐng)求,嘗試再次提交當(dāng)前任務(wù)。(3)CallerRunsPolicy:只要線程池未關(guān)閉,該策略直接在調(diào)用者線程中,運(yùn)行當(dāng)前被丟棄的任務(wù)。用線程池中的線程執(zhí)行,而是交給調(diào)用方來(lái)執(zhí)行,如果添加到線程池失敗,那么主線程會(huì)自己去執(zhí)行該任務(wù),不會(huì)等待線程池中的線程去執(zhí)行。(4)DiscardPolicy:丟棄無(wú)法處理的任務(wù),不給予任何處理。(5)自定義拒絕策略如果需要自定義策略,可以實(shí)現(xiàn)RejectedExecutionHandler接口。線程池中的線程是怎么創(chuàng)建的?是一開(kāi)始就隨著線程池的啟動(dòng)創(chuàng)建好的嗎?顯然不是的。線程池默認(rèn)初始化后不啟動(dòng)Worker,等待有請(qǐng)求時(shí)才啟動(dòng)。每當(dāng)我們調(diào)用execute()方法添加一個(gè)任務(wù)時(shí),線程池會(huì)做如下判斷:如果正在運(yùn)行的線程數(shù)量小于corePoolSize,那么馬上創(chuàng)建線程運(yùn)行這個(gè)任務(wù);如果正在運(yùn)行的線程數(shù)量大于或等于corePoolSize,那么將這個(gè)任務(wù)放入隊(duì)列;如果這時(shí)候隊(duì)列滿了,而且正在運(yùn)行的線程數(shù)量小于maximumPoolSize,那么還是要?jiǎng)?chuàng)建非核心線程立刻運(yùn)行這個(gè)任務(wù);如果隊(duì)列滿了,而且正在運(yùn)行的線程數(shù)量大于或等于maximumPoolSize,那么線程池會(huì)拋出異常RejectExecutionException。既然提到可以通過(guò)配置不同參數(shù)創(chuàng)建出不同的線程池,那么Java中默認(rèn)實(shí)現(xiàn)好的線程池又有哪些呢?請(qǐng)比較它們的異同?1.SingleThreadExecutor線程池這個(gè)線程池只有一個(gè)核心線程在工作,也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)。如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束,那么會(huì)有一個(gè)新的線程來(lái)替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。corePoolSize:1,只有一個(gè)核心線程在工作。maximumPoolSize:1。keepAliveTime:0L。workQueue:newLinkedBlockingQueue<Runnable>(),其緩沖隊(duì)列是無(wú)界的。2.FixedThreadPool線程池FixedThreadPool是固定大小的線程池,只有核心線程。每次提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程,直到線程達(dá)到線程池的最大大小。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會(huì)補(bǔ)充一個(gè)新線程,多用于服務(wù)器。corePoolSize:nThreadsmaximumPoolSize:nThreadskeepAliveTime:0LworkQueue:newLinkedBlockingQueue<Runnable>(),其緩沖隊(duì)列是無(wú)界的。3.CachedThreadPool線程池CachedThreadPool是無(wú)界線程池,如果線程池的大小超過(guò)了處理任務(wù)所需要的線程,那么就會(huì)回收部分空閑(60秒不執(zhí)行任務(wù))線程,當(dāng)任務(wù)數(shù)增加時(shí),此線程池又可以智能的添加新線程來(lái)處理任務(wù)。線程池大小完全依賴于操作系統(tǒng)(或者說(shuō)JVM)能夠創(chuàng)建的最大線程大小。SynchronousQueue是一個(gè)是緩沖區(qū)為1的阻塞隊(duì)列。corePoolSize:0maximumPoolSize:Integer.MAX_VALUEkeepAliveTime:60LworkQueue:newSynchronousQueue<Runnable>(),一個(gè)是緩沖區(qū)為1的阻塞隊(duì)列。4.ScheduledThreadPool線程池ScheduledThreadPool:核心線程池固定,大小無(wú)限的線程池。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。創(chuàng)建一個(gè)周期性執(zhí)行任務(wù)的線程池。如果閑置,非核心線程池會(huì)在DEFAULT_KEEPALIVEMILLIS時(shí)間內(nèi)回收。corePoolSize:corePoolSizemaximumPoolSize:Integer.MAX_VALUEkeepAliveTime:DEFAULT_KEEPALIVE_MILLISworkQueue:newDelayedWorkQueue()什么是Java的內(nèi)存模型,Java中各個(gè)線程是怎么彼此看到對(duì)方的變量的?Java的內(nèi)存模型:定義了程序中各個(gè)變量的訪問(wèn)規(guī)則,即在虛擬機(jī)中將變量存儲(chǔ)到內(nèi)存和從內(nèi)存中取出這樣的底層細(xì)節(jié)。此處的變量包括實(shí)例字段、靜態(tài)字段和構(gòu)成數(shù)組對(duì)象的元素,但是不包括局部變量和方法參數(shù),因?yàn)檫@些是線程私有的,不會(huì)被共享,所以不存在競(jìng)爭(zhēng)問(wèn)題。Java中各個(gè)線程是怎么彼此看到對(duì)方的變量的呢?Java中定義了主內(nèi)存與工作內(nèi)存的概念:所有的變量都存儲(chǔ)在主內(nèi)存,每條線程還有自己的工作內(nèi)存,保存了被該線程使用到的變量的主內(nèi)存副本拷貝。線程對(duì)變量的所有操作(讀取、賦值)都必須在工作內(nèi)存中進(jìn)行,不能直接讀寫(xiě)主內(nèi)存的變量。不同的線程之間也無(wú)法直接訪問(wèn)對(duì)方工作內(nèi)存的變量,線程間變量值的傳遞需要通過(guò)主內(nèi)存。Java內(nèi)存模型只保證了基本讀取和賦值是原子性操作,如果要實(shí)現(xiàn)更大范圍操作的原子性,可以通過(guò)synchronized和Lock來(lái)實(shí)現(xiàn)。由于synchronized和Lock能夠保證任一時(shí)刻只有一個(gè)線程執(zhí)行該代碼塊,那么自然就不存在原子性問(wèn)題了,從而保證了原子性。請(qǐng)談?wù)剉olatile關(guān)鍵字有什么特點(diǎn),為什么它能保證變量對(duì)所有線程的可見(jiàn)性?是不是就意味著基于volatile變量的運(yùn)算就是并發(fā)安全的?Volatile:是關(guān)鍵字,作用于變量上??梢?jiàn)性:上面說(shuō)到變量分為主內(nèi)存和工作內(nèi)存,如果是普通變量,每個(gè)線程在運(yùn)行過(guò)程中都有自己的工作內(nèi)存,那么線程1在運(yùn)行的時(shí)候,會(huì)將stop變量的值拷貝一份放在自己的工作內(nèi)存當(dāng)中。那么當(dāng)線程2更改了stop變量的值之后,但是還沒(méi)來(lái)得及寫(xiě)入主存當(dāng)中,線程2轉(zhuǎn)去做其他事情了,那么線程1由于不知道線程2對(duì)stop變量的更改,因此還會(huì)一直循環(huán)下去。但是用volatile修飾之后就變得不一樣了:第一:使用volatile關(guān)鍵字會(huì)強(qiáng)制將修改的值立即寫(xiě)入主存;第二:使用volatile關(guān)鍵字的話,當(dāng)線程2進(jìn)行修改時(shí),會(huì)導(dǎo)致線程1的工作內(nèi)存中緩存變量stop的緩存行無(wú)效(反映到硬件層的話,就是CPU的L1或者L2緩存中對(duì)應(yīng)的緩存行無(wú)效);第三:由于線程1的工作內(nèi)存中緩存變量stop的緩存行無(wú)效,所以線程1再次讀取變量stop的值時(shí)會(huì)去主存讀取。原子性:volatile沒(méi)辦法保證對(duì)變量的操作的原子性。即對(duì)int類型的自增變量,自增操作是不具備原子性的,它包括讀取變量的原始值、進(jìn)行加1操作、寫(xiě)入工作內(nèi)存三個(gè)階段,如果在第一個(gè)階段執(zhí)行完成后線程阻塞,那就有可能導(dǎo)致計(jì)算錯(cuò)誤。Volatile的操作是保證一個(gè)線程對(duì)變量修改后能立即寫(xiě)入主內(nèi)存,同時(shí)其他線程也會(huì)立即知道該變量失效并重新讀取值。并發(fā)安全:顯然不是并發(fā)安全,原因在于原子性,Java里面的運(yùn)算并非原子操作,加減乘除都不是原子操作。請(qǐng)對(duì)比下volatile對(duì)比Synchronized的異同?Synchronized既能保證可見(jiàn)性,又能保證原子性,而volatile只能保證可見(jiàn)性,無(wú)法保證原子性。請(qǐng)對(duì)比下ThreadLocal對(duì)比Synchronized的異同?Synchronized用于實(shí)現(xiàn)同步機(jī)制,是利用鎖的機(jī)制使變量或代碼塊在某一時(shí)該只能被一個(gè)線程訪問(wèn),是一種“以時(shí)間換空間”的方式。而ThreadLocal為每一個(gè)線程都提供了變量的副本,使得每個(gè)線程在某一時(shí)間訪問(wèn)到的并不是同一個(gè)對(duì)象,根除了對(duì)變量的共享,是一種“以空間換時(shí)間”的方式。如何在Java線程池中提交線程?答:submit(返回futhure對(duì)象,可以通過(guò)該對(duì)象的get方法獲取線程執(zhí)行結(jié)果,但是該操作是同步的,也就是主線程會(huì)阻塞)和excute。Java強(qiáng)引用、軟引用、弱引用、虛引用?強(qiáng)引用:我們使用的大部分引用其實(shí)都是強(qiáng)引用,也就是說(shuō)方法的內(nèi)部有一個(gè)強(qiáng)引用,這個(gè)引用保存在棧中,而真正的引用內(nèi)容(Object)保存在堆中。當(dāng)這個(gè)方法運(yùn)行完成后就會(huì)退出方法棧,則引用內(nèi)容的引用不存在,這個(gè)Object會(huì)被回收。但是如果這個(gè)對(duì)象是全局的變量時(shí),就需要在不用這個(gè)對(duì)象時(shí)賦值為null,因?yàn)閺?qiáng)引用不會(huì)被垃圾回收。軟引用:軟引用是用來(lái)描述一些有用但并不是必需的對(duì)象,在Java中用java.lang.ref.SoftReference類來(lái)表示。對(duì)于軟引用關(guān)聯(lián)著的對(duì)象,只有在內(nèi)存不足的時(shí)候JVM才會(huì)回收該對(duì)象。如果一個(gè)對(duì)象只有軟引用,就類似雞肋,食之無(wú)味、棄之可惜,如果內(nèi)存空間足夠大,垃圾回收期就不會(huì)回收它,如果內(nèi)存空間不夠了,就會(huì)回收這些對(duì)象。只有垃圾回收器沒(méi)有回收它,該對(duì)象就可以被程序使用。軟引用可用來(lái)實(shí)現(xiàn)內(nèi)存敏感的高速緩存。弱引用:在java中,用java.lang.ref.WeakReference類來(lái)表示。弱引用和軟引用的區(qū)別在于:弱引用的對(duì)象具有更短暫的生命周期。在垃圾回收時(shí),一旦發(fā)現(xiàn)了只具有弱引用的對(duì)象,不管當(dāng)前內(nèi)存空間足夠與否,都會(huì)回收它的內(nèi)存。虛引用:就是形同虛設(shè),與其他幾種引用都不同,虛引用并不會(huì)決定對(duì)象的生命周期。在java中用java.lang.ref.PhantomReference類表示。如果一個(gè)對(duì)象僅持有虛引用,那么它就和沒(méi)有任何引用一樣,在任何時(shí)候都可能被垃圾回收。ThreadLocal原理?原理:每個(gè)Thread都有自己的一個(gè)ThreadLocal.ThreadLocalMap對(duì)象。key是TreadLocal實(shí)例對(duì)象,value就是你要保存的那個(gè)變量。當(dāng)前線程Thread中有一個(gè)ThreadLocalMap對(duì)象,它的key是ThreadLocal的弱引用,Value是ThreadLocal調(diào)用set方法設(shè)置的對(duì)象值。每一個(gè)線程維護(hù)一個(gè)各自的ThreadLocalMap,所以多個(gè)線程之間變量相互隔離,互不干擾。缺點(diǎn):存在內(nèi)存泄漏問(wèn)題,因?yàn)楫?dāng)Thr

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論