後端開發面試總結

String爲什麼是final的

從設計安全上講, 
1)、確保它們不會在子類中改變語義。String類是final類,這意味着不允許任何人定義String的子類。
換言之,如果有一個String的引用,它引用的一定是一個String對象,而不可能是其他類的對象
從效率上講: 
1)、設計成final,JVM纔不用對相關方法在虛函數表中查詢,而直接定位到String類的相關方法上,提高了執行效率。 
2)、Java設計者認爲共享帶來的效率更高

 

spring MVC中的controller是單例模式(只是表示多個請求變量共享),但是是多線程,各個線程之間不影響!

spring mvc 的Controller類默認Scope是單例(singleton)的

By Lee - Last updated: 星期一, 二月 10, 2014 Leave a Comment

使用Spring MVC有一段時間了,之前一直使用Struts2,在struts2中action都是原型(prototype)的, 說是因爲線程安全問題,對於Spring MVC中bean默認都是(singleton)單例的,那麼用@Controller註解標籤注入的Controller類是單例實現的?

測試結果發現spring3中的controller默認是單例的,若是某個controller中有一個私有的變量i,所有請求到同一個controller時,使用的i變量是共用的,即若是某個請求中修改了這個變量a,則,在別的請求中能夠讀到這個修改的內容。 若是在@Controller之前增加@Scope(“prototype”),就可以改變單例模式爲多例模式

 

redis與memcached的區別

0.Redis只使用單核,而Memcached可以使用多核

1.存儲方式:

    memecache 把數據全部存在內存之中,斷電後會掛掉,數據不能超過內存大小

    redis有部份存在硬盤上,這樣能保證數據的持久性,支持數據的持久化

2.數據支持類型:

    redis在數據支持上要比memecache多的多。

- Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。

 

3.使用底層模型不同:

    新版本的redis直接自己構建了VM 機制 ,因爲一般的系統調用系統函數的話,會浪費一定的時間去移動和請求。

4.運行環境不同:

    redis目前官方只支持Linux 上去行,從而省去了對於其它系統的支持,這樣的話可以更好的把精力用於本系統 環境上的優化,雖然後來微軟有一個小組爲其寫了補丁。但是沒有放到主幹上

 

設計模式的六大原則

.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;F:\Program Files\IBM\WebSphere MQ\java\lib\com.ibm.mqjms.jar;F:\Program Files\IBM\WebSphere MQ\java\lib\com.ibm.mq.jar

單一職責原則告訴我們實現類要職責單一;里氏替換原則告訴我們不要破壞繼承體系(對類進行修改時儘量不要重寫父類方法也不要重載父類方法);依賴倒置原則告訴我們要面向接口編程(高層不應該依賴於底層而是依賴於抽象,底層不應該依賴於細節也是依賴於抽象);接口隔離原則告訴我們在設計接口的時候要精簡單一;迪米特法則告訴我們要降低耦合。而開閉原則是總綱,他告訴我們要對擴展開放,對修改關閉。

 

面向對象特徵:抽象,繼承,封裝,多態

 

有2種辦法讓HashMap線程安全,分別如下:
  方法一:通過Collections.synchronizedMap()返回一個新的Map,這個新的map就是線程安全的。 這個要求大家習慣基於接口編程,因爲返回的並不是HashMap,而是一個Map的實現。

  方法二:重新改寫了HashMap,具體的可以查看java.util.concurrent.ConcurrentHashMap. 這個方法比方法一有了很大的改進。

 

collection與collections的區別

     Collection 是集合類的上級接口,繼承與他的接口主要有Set 和List.

Collections 是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安

全化等操作。

 

sleep() 和wait() 有什麼區別?

sleep 是線程類(Thread )的方法,導致此線程暫停執行指定時間,給執行機會給其他線程,但是監控

狀態依然保持,到時後會自動恢復。調用 sleep 不會釋放對象鎖。

wait 是Object 類的方法,對此對象調用 wait 方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定

池,只有針對此對象發出notify 方法(或notifyAll )後本線程才進入對象鎖定池準備獲得對象鎖進入運

行狀態。

 

如果一個類繼承Thread,則不適合資源共享。但是如果實現了Runable接口的話,則很容易的實現資源共享。

 

 

在java代碼中,如果調用方法後可能會出現異常,則必須對異常進行處理,寫java代碼時自動拋出的異常稱爲檢測性異常,例如在寫文件時會自動拋出IOException;有些異常不會自動拋出,比如在執行parseIntger()方法時,如果括號中的參數不可以轉換爲整數,則會拋出異常,應用程序會終止,而在寫代碼的時候卻不需要處理這個異常,這樣的異常稱爲非檢測性異常

 

 

給我一個你最常見到的runtime exception

ArithmeticException, ArrayStoreException, BufferOverflowException,

BufferUnderflowException, CannotRedoException, CannotUndoException,

ClassCastException, CMMException, ConcurrentModificationException, DOMException,

EmptyStackException, IllegalArgumentException ( 不合法的參數異常) ,

IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,

ImagingOpException, IndexOutOfBoundsException, MissingResourceException,

NegativeArraySizeException, NoSuchElementException, NullPointerException,

ProfileDataException, ProviderException, RasterFormatException, SecurityException,

SystemException, UndeclaredThrowableException, UnmodifiableSetException,

UnsupportedOperationException

 

 

單例模式

class Singleton{

     private static Singleton instance=null;

     public static synchronized Singleton getInstance(){

               if(instance ==null)

                    return new Singleton ();

               return instance;

     }

}

 

AOP的jdk動態代理技術

要了解這個要先了解代理模式(爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用)

靜態代理就如設計模式中所講,其中優點:1.客戶端和代理對象的橋樑2.無侵入的增強業務代碼3.增強點多樣化(在做被代理的對象的事情時可以在代理前入,後入,異常增加自己的業務),其中缺點:擴展能力差,可維護性差

其中根據配置的被攔截的類的名稱來獲取其實例然後代理涉及到java反射機制

  1.     /* 
  2.     User u = new User(); 
  3.     u.age = 12; //set 
  4.     System.out.println(u.age); //get 
  5.     */  
  6.               
  7.     //獲取類  
  8.     Class c = Class.forName("User");  
  9.     //獲取id屬性  
  10.     Field idF = c.getDeclaredField("id");  
  11.     //實例化這個類賦給o  
  12.     Object o = c.newInstance();  
  13.     //打破封裝  
  14.     idF.setAccessible(true); //使用反射機制可以打破封裝性,導致了java對象的屬性不安全。  
  15.     //給o對象的id屬性賦值"110"  
  16.     idF.set(o, "110"); //set  
  17.     //get  
  18.     System.out.println(idF.get(o));  

 

也可通過另外一種方式來注入值,其中TntBaseInterface的屬性在被攔截的方法中的參數對象裏面的屬性一定存在並一致

 

 

 

 

1.整型
類型              存儲需求        bit數                  取值範圍     
byte                 1字節           1*8      (-2的31次方到2的31次方-1)
short                2字節           2*8             -32768~32767
int                    4字節           4*8      (-2的63次方到2的63次方-1)
long                 8字節           8*8                 -128~127

2.浮點型
類型              存儲需求         bit數                                  備註
float                  4字節           4*8            float類型的數值有一個後綴F(例如:3.14F)
double              8字節           8*8         沒有後綴F的浮點數值(如3.14)默認爲double類型

3.char類型
類型              存儲需求        bit數 

char                  2字節          2*8

 

一箇中文佔兩個字節,一個英文字母佔一個字節

 

多線程有兩種實現方法,分別是繼承 Thread 類與實現Runnable 接口

同步的實現方面有兩種,分別是 synchronized,wait 與notify

 

servlet返回ajax數據

 PrintWriter out = response.getWriter();

  out.println("1");

 

Java 中的線程有四種狀態分別是:運行、就緒、掛起、結束

 

 

Map是java中的接口,Map.Entry是Map的一個內部接口。

Map提供了一些常用方法,如keySet()、entrySet()等方法。

keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一個Set集合,此集合的類型爲Map.Entry。

Map.Entry是Map聲明的一個內部接口,此接口爲泛型,定義爲Entry<K,V>。它表示Map中的一個實體(一個key-value對)。接口中有getKey(),getValue方法。

            TreeMap<Integer, Integer> tm= new TreeMap<Integer,Integer>();

            tm.put(1, 1);

            tm.put(2, 2);

            Iterator<Entry<Integer, Integer>> it=tm.entrySet().iterator();

             while(it.hasNext()){

                  System. out.println(it.next().getValue()+ "值");

            }

 

Spring

控制反轉,和依賴注入是同一個意思,我覺得應該重點去了解什麼是依賴,而後控制反轉、依賴注入就有體會了;關於依賴,可以查看UML相關的書籍,重點去看java對象之間的關係是怎樣的,而所謂的依賴就是對象之間的一種關係,比如a對象依賴於b對象,那麼a類中就會有b類的引用(簡單理解就是擁有b類的這麼一個屬性),也就是說a對象要想執行一個完整的功能,必須建立一個前提——a對象中的b類屬性已經實例話,並且擁有b類的一切功能;現在可以去了解什麼是依賴注入了,就像前面說過的,a對象想完成一個完整的功能,要先爲自己的b類屬性實例化,而在MVC模式中,這種現象很常見,爲了簡化這種實例化的工作,spring容器就產生了,它可以統一管理這種實例化頻繁的操作,就是說這種本來應由自己實例化的工作交給Spring容器去控制了,也就是說控制反轉了,實現的方案之一是在上述a類中提供一個關於b類的setter方法,這個方法會被Spring容器控制。

AOP,還是以上面的例子。

比如你想在每次寫字之前都檢查一下筆裏有沒有墨水了,通常的做法是:在寫字這個Action裏調用判斷是否有墨水的方法。這樣做的不好一個方面是,寫字的action和是否有墨水的方法產生了依賴,如果你有十幾支不同的筆寫字,每一個筆的Action裏都要調用判斷是否有墨水的方法;另一個方面是:就面向對象的程序設計來說,寫字和判斷是否有墨水的方法是同一等級的,如果你讓寫字這個動作來判斷是否有墨水不夠人性化,有違面向對象的程序設計的思想。
如果用Spring的AOP,是把寫字的Action作爲一個切面,在每次調用不同的筆來寫字的方法之前,調用判斷是否有墨水的方法。它是由<aop:config/>標籤在Spring配置文件裏定義的,形式如:
<aop:config>
   <aop:pointcut id="allManagerMethod" expression="execution(* com.baidu.dao.write*(..))"/>
    <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/>
</aop:config>

這裏,對com.baidu.dao下所有以write開頭的方法做了一個切面,做要做的操作是以下面的pointcut-ref="allManagerMethod"來定義的。

 

Aop應用場景

數據庫事務處理

實現登錄的日誌管理

 

 

SpringMVC運行原理

 

- 客戶端請求提交到DispatcherServlet

- 由DispatcherServlet控制器查詢一個或多個HandlerMapping,找到處理請求的Controller

- DispatcherServlet將請求提交到Controller

- Controller調用業務邏輯處理後,返回ModelAndView

- DispatcherServlet查詢一個或多個ViewResoler視圖解析器,找到ModelAndView指定的視圖

- 視圖負責將結果顯示到客戶端

 

java集合框架圖

 

 

 

函數式編程(FP)是一種軟件開發風格,它注重不依賴於編程狀態的函數(是動態的)。函數式代碼易於測試和複用,容易實現併發,且不容易受到bug的攻擊(通過函數之間的互相調用完成功能)

 

之所以靜態的方法不可以訪問非靜態的方法,因爲靜態static是靜態的實例資源,而非靜態的方法還沒有創建實例

 

垃圾回收器的基本原理是什麼?垃圾回收器可以馬上回收內存嗎?有什麼辦法主動通知虛擬機進行垃圾回收?

 

對於 GC 來說,當程序員創建對象時, GC 就開始監控這個對象的地址、大小以及使用情況。通常, GC

採用有向圖的方式記錄和管理堆(heap)中的所有對象。通過這種方式確定哪些對象是 "可達的" ,哪些對

象是 "不可達的" 。當GC 確定一些對象爲 "不可達" 時,GC 就有責任回收這些內存空間。可以。程序員可

以手動執行 System.gc(),通知GC 運行,但是 Java 語言規範並不保證GC 一定會執行。

 

 

Spring既是一個AOP框架,也是一IOC容器。 Spring 最好的地方是它有助於您替換對象。有了 Spring,只要用 JavaBean 屬性和配置文件加入依賴性(協作對象)。然後可以很容易地在需要時替換具有類似接口的協作對象

 

JavaBean是一個組件,而EJB就是一個組件框架

 

JavaBean面向的是業務邏輯和表示層的顯示,通過編寫一個JavaBean,可以將業務邏輯的事件和事務都放在其中,然後通過它的變量屬性將所需要的內容在表示層傳遞顯示。

EJB是部署在服務器上的可執行組件或商業對象。EJB有一個部署描述符,通過這個部署描述符可以對EJB的屬性進行描述。EJB不和表示層交互

首先,EJB是指運行在EJB容器中的JavaBean。Tomcat是Web容器的參考實現。一個完整的JavaEE服務器應該包括Web容器和 EJB容器。

其次,Web容器中無法運行EJB,同時所有的JavaBean都是在服務器端運行的。如果有在客戶端的話,就變成C/S結構了。

 

 

spring工作原理:  

1.spring mvc請所有的請求都提交給DispatcherServlet,它會委託應用系統的其他模塊負責負責對請求進行真正的處理工作。  2.DispatcherServlet查詢一個或多個HandlerMapping,找到處理請求的Controller. 

3.DispatcherServlet請請求提交到目標Controller  

4.Controller進行業務邏輯處理後,會返回一個ModelAndView 

5.Dispathcher查詢一個或多個ViewResolver視圖解析器,找到ModelAndView對象指定的視圖對象 

6.視圖對象負責渲染返回給客戶端。

 

struts2工作原理:

 1.客戶端(Client)向Action發用一個請求(Request)

 2.Container通過web.xml映射請求,並獲得控制器(Controller)的名字

 3.容器(Container)調用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前調用FilterDispatcher,Struts2.1以後調用StrutsPrepareAndExecuteFilter

 4.控制器(Controller)通過ActionMapper獲得Action的信息

 5.控制器(Controller)調用ActionProxy

 6.ActionProxy讀取struts.xml文件獲取action和interceptor stack的信息。

 7.ActionProxy把request請求傳遞給ActionInvocation

 8.ActionInvocation依次調用action和interceptor

 9. 根據action的配置信息,產生result

 10.Result信息返回給ActionInvocation

 11.產生一個HttpServletResponse響應

 12.產生的響應行爲發送給客服端。

 

springmvc與struts2的區別:

1、Struts2是類級別的攔截, 一個類對應一個request上下文,SpringMVC是方法級別的攔截,一個方法對應一個request上下文,而方法同時又跟一個url對應,所以說從架構本身上SpringMVC就容易實現restful url,而struts2的架構實現起來要費勁,因爲Struts2中Action的一個方法可以對應一個url,而其類屬性卻被所有方法共享,這也就無法用註解或其他方式標識其所屬方法了。

2、由上邊原因,SpringMVC的方法之間基本上獨立的,獨享request response數據,請求數據通過參數獲取,處理結果通過ModelMap交回給框架,方法之間不共享變量,而Struts2搞的就比較亂,雖然方法之間也是獨立的,但其所有Action變量是共享的,這不會影響程序運行,卻給我們編碼 讀程序時帶來麻煩,每次來了請求就創建一個Action,一個Action對象對應一個request上下文。
3、由於Struts2需要針對每個request進行封裝,把request,session等servlet生命週期的變量封裝成一個一個Map,供給每個Action使用,並保證線程安全,所以在原則上,是比較耗費內存的。

4、 攔截器實現機制上,Struts2有以自己的interceptor機制,SpringMVC用的是獨立的AOP方式,這樣導致Struts2的配置文件量還是比SpringMVC大。

5、SpringMVC的入口是servlet,而Struts2是filter(這裏要指出,filter和servlet是不同的。以前認爲filter是servlet的一種特殊),這就導致了二者的機制不同,這裏就牽涉到servlet和filter的區別了。

6、SpringMVC集成了Ajax,使用非常方便,只需一個註解@ResponseBody就可以實現,然後直接返回響應文本即可,而Struts2攔截器集成了Ajax,在Action中處理時一般必須安裝插件或者自己寫代碼集成進去,使用起來也相對不方便。

7、SpringMVC驗證支持JSR303,處理起來相對更加靈活方便,而Struts2驗證比較繁瑣,感覺太煩亂。

8、spring MVC和Spring是無縫的。從這個項目的管理和安全上也比Struts2高(當然Struts2也可以通過不同的目錄結構和相關配置做到SpringMVC一樣的效果,但是需要xml配置的地方不少)。

9、 設計思想上,Struts2更加符合OOP的編程思想, SpringMVC就比較謹慎,在servlet上擴展。

10、SpringMVC開發效率和性能高於Struts2。

11、SpringMVC可以認爲已經100%零配置。

SSH: 

Struts(表示層)+Spring(業務層)+Hibernate(持久層)

Struts:  Struts是一個表示層框架,主要作用是界面展示,接收請求,分發請求。  在MVC框架中,Struts屬於VC層次,負責界面表現,負責MVC關係的分發。(View:沿 用JSP,HTTP,Form,Tag,Resourse ;Controller:ActionServlet,struts-config.xml,Action)

Hibernate:  Hibernate是一個持久層框架,它只負責與關係數據庫的操作。

Spring:  Spring是一個業務層框架,是一個整合的框架,能夠很好地黏合表示層與持久層。

 

struts1和struts2的區別:

Action 類:

• Struts1要求Action類繼承一個抽象基類。Struts1的一個普遍問題是使用抽象類編程而不是接口,而struts2的Action是接口。

• Struts 2 Action類可以實現一個Action接口,也可實現其他接口,使可選和定製的服務成爲可能。Struts2提供一個ActionSupport基類去 實現 常用的接口。Action接口不是必須的,任何有execute標識的POJO對象都可以用作Struts2的Action對象。

線程模式:

• Struts1 Action是單例模式並且必須是線程安全的,因爲僅有Action的一個實例來處理所有的請求。單例策略限制了Struts1 Action能作的事,並且要在開發時特別小心。Action資源必須是線程安全的或同步的。

• Struts2 Action對象爲每一個請求產生一個實例,因此沒有線程安全問題。(實際上,servlet容器給每個請求產生許多可丟棄的對象,並且不會導致性能和垃圾回收問題)

 

 

hibernate

工作原理:

1. 讀取並解析配置文件

2. 讀取並解析映射信息,創建SessionFactory

3. 打開Sesssion

4. 創建事務Transation

5. 持久化操作

6. 提交事務

7. 關閉Session

8. 關閉SesstionFactory
工作流程:
 (1)先是創建pojo類(javaBean)
 (2)再是創建映射文件(.hbm.xml)
 (3)創建配置文件(hibernate.hbm.xml) 

 (4)後調用Hibernate API對數據庫進行CRUD操作.

hibernate與mybatics的區別

1. hibernate是全自動,而mybatis是半自動。

2. hibernate數據庫移植性遠大於mybatis。

3. hibernate擁有完整的日誌系統,mybatis則欠缺一些。

hibernate日誌系統非常健全,涉及廣泛,包括:sql記錄、關係異常、優化警告、緩存提示、髒數據警告等;而mybatis則除了基本記錄功能外,功能薄弱很多。

4. mybatis相比hibernate需要關心很多細節

5. sql直接優化上,mybatis要比hibernate方便很多

由於mybatis的sql都是寫在xml裏,因此優化sql比hibernate方便很多。而hibernate的sql很多都是自動生成的,無法直接維護sql;雖有hql,但功能還是不及sql強大,見到報表等變態需求時,hql也歇菜,也就是說hql是有侷限的;hibernate雖然也支持原生sql,但開發模式上卻與orm不同,需要轉換思維,因此使用上不是非常方便。總之寫sql的靈活度上hibernate不及mybatis。

 

spring中的BeanFactory與ApplicationContext的作用有哪些

1. BeanFactory負責讀取bean配置文檔,管理bean的加載,實例化,維護bean之間的依賴關係,負責bean的聲明週期。 

2. ApplicationContext除了提供上述BeanFactory所能提供的功能之外,還提供了更完整的框架功能:

  a. 國際化支持 

  b. 資源訪問:Resource rs = ctx. getResource(”classpath:config.properties”), “file:c:/config.properties”   

  c. 事件傳遞:通過實現ApplicationContextAware接口

 

常用的獲取ApplicationContext的方法:

可以配置監聽器或者servlet來實現

<listener> 

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

 

 

 

三種方式可以得到Bean並進行調用:

1、使用  BeanWrapper 

HelloWorldhw=new HelloWorld();   

BeanWrapperbw=new BeanWrapperImpl(hw); 

bw.setPropertyvalue(”msg”,”HelloWorld”); 

system.out.println(bw.getPropertyCalue(”msg”));   

2、使用BeanFactory 

InputStream is=new FileInputStream(”config.xml”); 

XmlBeanFactory factory=new XmlBeanFactory(is); 

HelloWorldhw=(HelloWorld) factory.getBean(”HelloWorld”); 

system.out.println(hw.getMsg());   

3、使用ApplicationConttext 

ApplicationContextactx=new FleSystemXmlApplicationContext(”config.xml”);

HelloWorldhw=(HelloWorld) actx.getBean(”HelloWorld”);

System.out.println(hw.getMsg());

 

ORM

對象關係映射(英語:Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用於實現面向對象編程語言裏不同類型系統的數據之間的轉換。從效果上說,它其實是創建了一個可在編程語言裏使用的“虛擬對象數據庫”。

 

寫clone()方法時通常有一行代碼,是什麼

clone有缺省行爲,super.clone();他負責產生正確大小的空間,並逐位複製

 

Clone方法

class CloneClass implements Cloneable{ 
 public int aInt; 
 public Object clone(){ 
  CloneClass o = null; 
  try{ 
   o = (CloneClass)super.clone(); 
  }catch(CloneNotSupportedException e){ 
   e.printStackTrace(); 
  } 
  return o; 
 } 

 

 

 

序列化和反序列化

概念

  把對象轉換爲字節序列的過程稱爲對象的序列化。

  把字節序列恢復爲對象的過程稱爲對象的反序列化。

 

應用場景

 在很多應用中,需要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。比如最常見的是Web服務器中的Session對象,當有 10萬用戶併發訪問,就有可能出現10萬個Session對象,內存可能喫不消,於是Web容器就會把一些seesion先序列化到硬盤中,等要用了,再把保存在硬盤中的對象還原到內存中。

  當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個Java對象轉換爲字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復爲Java對象。

 

    java.io.ObjectOutputStream代表對象輸出流,它的writeObject(Object obj)方法可對參數指定的obj對象進行序列化,把得到的字節序列寫到一個目標輸出流中。
  java.io.ObjectInputStream代表對象輸入流,它的readObject()方法從一個源輸入流中讀取字節序列,再把它們反序列化爲一個對象,並將其返回。
  只有實現了Serializable和Externalizable接口的類的對象才能被序列化。Externalizable接口繼承自 Serializable接口,實現Externalizable接口的類完全由自身來控制序列化的行爲,而僅實現Serializable接口的類可以 採用默認的序列化方式 。

 

對象序列化包括如下步驟:

  1) 創建一個對象輸出流,它可以包裝一個其他類型的目標輸出流,如文件輸出流;

  2) 通過對象輸出流的writeObject()方法寫對象。


  對象反序列化的步驟如下:

  1) 創建一個對象輸入流,它可以包裝一個其他類型的源輸入流,如文件輸入流;

  2) 通過對象輸入流的readObject()方法讀取對象。

 

 

 

多線程同步機制包括:

1.Event事件(一個事件具有兩種狀態:有信號狀態,無信號狀態)

2.臨界區Critical Section(使用臨界區域的第一個忠告就是不要長時間鎖住一份資源 )

3.互斥器Mutex

4.信號量Semaphore

信號量 是最具歷史的同步機制。信號量是解決producer/consumer 問題的關鍵要素。

對應的MFC 類是Csemaphore。Win32 函數 CreateSemaphore ()用來產生信號量。

ReleaseSemaphore()用來解除鎖定。Semaphore 的現值代表的意義是可用的資源數,

如果Semaphore 的現值爲1,表示還有一個鎖定動作可以成功。如果現值爲5,就表示還

有五個鎖定動作可以成功。當調用Wait…等函數要求鎖定,如果Semaphore 現值不爲0,

Wait…馬上返回,資源數減1。當調用ReleaseSemaphore()資源數加1,當然不會超過

初始設定的資源總數。

 

 class ClassA {}

 class ClassB extends ClassA {}

 class ClassC extends ClassA {}

and:

 ClassA p0 = new ClassA();

 ClassB p1 = new ClassB();

 ClassC p2 = new ClassC();

 ClassA p3 = new ClassB();

 ClassA p4 = new ClassC();

Which three are valid? (Choose three.)

A. p0 = p1;

B. p1 = p2;

C. p2 = p4;

D. p2 = (ClassC)p1;

E. p1 = (ClassB)p3;

F. p2 = (ClassC)p4;

 

 

答案:AEF

考點:繼承環境下的引用變量指向

說明:

      父類引用變量可以指向子類對象; 子類引用變量不能指向父類對象。

      擁有同一父類的兄弟類之間不能互相指向。

 

 技術演進出來的數據庫連接池

          我們知道,對於共享資源,有一個很著名的設計模式:資源池(resource pool)。該模式正是爲了解決資源的頻繁分配﹑釋放所造成的問題。爲解決上述問題,可以採用數據庫連接池技術。數據庫連接池的基本思想就是爲數據庫連接建立一個“緩衝池”。預先在緩衝池中放入一定數量的連接,當需要建立數據庫連接時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。我們可以通過設定連接池最大連接數來防止系統無盡的與數據庫連接。更爲重要的是我們可以通過連接池的管理機制監視數據庫的連接的數量﹑使用情況,爲系統開發﹑測試及性能調整提供依據。

 

三.連接池還要考慮更多的問題

       1、併發問題

       爲了使連接管理服務具有最大的通用性,必須考慮多線程環境,即併發問題。這個問題相對比較好解決,因爲java語言自身提供了對併發管理的支持,使用synchronized關鍵字即可確保線程是同步的。使用方法爲直接在類方法前面加上synchronized關鍵字,如:

      publicsynchronized connection getconnection()

 

       2、多數據庫服務器和多用戶

       對於大型的企業級應用,常常需要同時連接不同的數據庫(如連接oracle和sybase)。如何連接不同的數據庫呢?我們採用的策略是:設計一個符合單例模式的連接池管理類,在連接池管理類的唯一實例被創建時讀取一個資源文件,其中資源文件中存放着多個數據庫的url地址等信息。根據資源文件提供的信息,創建多個連接池類的實例,每一個實例都是一個特定數據庫的連接池。連接池管理類實例爲每個連接池實例取一個名字,通過不同的名字來管理不同的連接池。

       對於同一個數據庫有多個用戶使用不同的名稱和密碼訪問的情況,也可以通過資源文件處理,即在資源文件中設置多個具有相同url地址,但具有不同用戶名和密碼的數據庫連接信息。

 

       3、事務處理

       我們知道,事務具有原子性,此時要求對數據庫的操作符合“all-all-nothing”原則即對於一組sql語句要麼全做,要麼全不做。

       在java語言中,connection類本身提供了對事務的支持,可以通過設置connection的autocommit屬性爲false 然後顯式的調用commit或rollback方法來實現。但要高效的進行connection複用,就必須提供相應的事務支持機制。可採用每一個事務獨佔一個連接來實現,這種方法可以大大降低事務管理的複雜性。

 

       4、連接池的分配與釋放

       連接池的分配與釋放,對系統的性能有很大的影響。合理的分配與釋放,可以提高連接的複用度,從而降低建立新連接的開銷,同時還可以加快用戶的訪問速度。

       對於連接的管理可使用空閒池。即把已經創建但尚未分配出去的連接按創建時間存放到一個空閒池中。每當用戶請求一個連接時,系統首先檢查空閒池內有沒有空閒連接。如果有就把建立時間最長(通過容器的順序存放實現)的那個連接分配給他(實際是先做連接是否有效的判斷,如果可用就分配給用戶,如不可用就把這個連接從空閒池刪掉,重新檢測空閒池是否還有連接);如果沒有則檢查當前所開連接池是否達到連接池所允許的最大連接數(maxconn)如果沒有達到,就新建一個連接,如果已經達到,就等待一定的時間(timeout)。如果在等待的時間內有連接被釋放出來就可以把這個連接分配給等待的用戶,如果等待時間超過預定時間timeout 則返回空值(null)。系統對已經分配出去正在使用的連接只做計數,當使用完後再返還給空閒池。對於空閒連接的狀態,可開闢專門的線程定時檢測,這樣會花費一定的系統開銷,但可以保證較快的響應速度。也可採取不開闢專門線程,只是在分配前檢測的方法。

 

       5、連接池的配置與維護

       連接池中到底應該放置多少連接,才能使系統的性能最佳?系統可採取設置最小連接數(minconn)和最大連接數(maxconn)來控制連接池中的連接。最小連接數是系統啓動時連接池所創建的連接數。如果創建過多,則系統啓動就慢,但創建後系統的響應速度會很快;如果創建過少,則系統啓動的很快,響應起來卻慢。這樣,可以在開發時,設置較小的最小連接數,開發起來會快,而在系統實際使用時設置較大的,因爲這樣對訪問客戶來說速度會快些。最大連接數是連接池中允許連接的最大數目,具體設置多少,要看系統的訪問量,可通過反覆測試,找到最佳點。

       如何確保連接池中的最小連接數呢?有動態和靜態兩種策略。動態即每隔一定時間就對連接池進行檢測,如果發現連接數量小於最小連接數,則補充相應數量的新連接以保證連接池的正常運轉。靜態是發現空閒連接不夠時再去檢查。

 

事務的四個特性

1、一致性:事務在完成時,必須使所有的數據都保持一致狀態,而且在相關數據中,所有規則都必須應用於事務的修改,以保持所有數據的完整性。事務結束時,所有的內部數據結構都應該是正確的。

 

2、原子性:將事務中所做的操作捆綁成一個原子單元,即對於事務所進行的數據修改等操作,要麼全部執行,要麼全部不執行。

 

3、隔離性:由併發事務所做的修改必須與任何其他事務所做的修改相隔離。事務查看數據時數據所處的狀態,要麼是被另一併發事務修改之前的狀態,要麼是被另一併發事務修改之後的狀態,即事務不會查看由另一個併發事務正在修改的數據。這種隔離方式也叫可串行性。

 

4、持久性:事務完成之後,它對系統的影響是永久的,即使出現系統故障也是如此。

 

事務問題

1. 髒讀 :髒讀就是指當一個事務正在訪問數據,並且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務也訪問 這個數據,然後使用了這個數據。

  比如事務1,修改了某個數據              事務2,剛好訪問了事務1修改後的數據

  此時事務1,回滾了操作                  事務2,讀到還是回滾前的數據

 

此時,事務2讀到的就是在內存中,而不是在數據庫中的數據(事務1還未提交)

 

2. 不可重複讀 :是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。那麼,在第一個事務中的兩 次讀數據之間,由於第二個事務的修改,那麼第一個事務兩次讀到的的數據可能是不一樣的。

 

事務1,查詢某個數據                   事務2,修改了某個數據,提交

事務1,再次查詢這個數據

這樣事務1兩次查詢的數據不一樣,稱爲不可重複讀

 

3. 幻讀 : 是值第一個事務查詢或操作一堆數據,事務2此時插入一條數據並提交,事務1再次查詢或操作時,突然發現多了一條數據,像是幻覺一樣。與不可重複讀類似,不過後者是修改了某一條,某條不同,而前者是增加了一條。

 

 

解決方案

編輯

爲了避免上面出現的幾種情況,在標準SQL規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同。

未授權讀取

也稱爲讀未提交(Read Uncommitted):允許髒讀取,但不允許更新丟失。如果一個事務已經開始寫數據,則另外一個事務則不允許同時進行寫操作,但允許其他事務讀此行數據。該隔離級別可以通過“排他寫鎖”實現。

授權讀取

也稱爲讀提交(Read Committed):允許不可重複讀取,但不允許髒讀取。這可以通過“瞬間共享讀鎖”和“排他寫鎖”實現。讀取數據的事務允許其他事務繼續訪問該行數據,但是未提交的寫事務將會禁止其他事務訪問該行。

可重複讀取(Repeatable Read)

可重複讀取(Repeatable Read):禁止不可重複讀取和髒讀取,但是有時可能出現幻讀數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

序列化(Serializable)

序列化(Serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接着一個地執行,不能併發執行。僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機制保證新插入的數據不會被剛執行查詢操作的事務訪問到。

 

 

web.xml默認加載順序

servlet-context=>listener=>filter=>servlet

 

數據庫中

char和vachar2的區別:char最大可以容納2個字節,varchar2最多可以容納4個字節,此爲可變長字段

 

統一認證實現機制

1.用戶通過瀏覽器訪問接入統一認證的應用系統,訪問地址如下:http://helloservice/main.jsp

2.應用系統發現用戶尚未登錄,將用戶瀏覽器重定向到統一認證CASServer的登錄界面, 同時在重定向的URL上用service參數將用戶的目標地址傳給CAS服務器,以及應用系統id(此值由統一認證分配), 地址如下:http://CASserver/login?service=http%3A%2F%2Fhelloservice%2Fmain.jsp&appid=1

3.CAS服務器發現用戶未登錄過CAS服務,顯示登錄頁面,用戶在CASServer的登錄頁面上輸入用戶名、密碼登錄,CASServer服務器認證通過後,生成一個ticket,並帶在目標地址的尾部返回給客戶端瀏覽器,地址如下:http://helloservice/main.jsp?ticket=CASticket

4.用戶瀏覽器重定向CASServer返回的URL地址。

5.應用系統獲得ticket憑證,並將appid一起,通過URL地址:http://CASserver/validate?ticket=CASticket&appid=1向CAS認證中心確認對應的服務請求和憑證是否有效。

6.CAS服務器返回的驗證結果,應用系統根據CAS服務器返回的結果,如果憑證有效,則通過結果獲取用戶號信息,並允許用戶進http://helloservice/main.jsp所指向的頁面;否則,再次重定向到http://CASserve/login?service=http%3A%2F%2Fhelloservice%2Fmain.jsp&appid=1上要求用戶進行認證。

 

 

jvm類加載器的過程

加載:就是將class二進制文件由類加載器加載到內存。

連接-驗證:主要驗證class文件的格式是否正確,語法是否正確,字節碼是否正確,二進制是否兼容。

連接-準備:爲類的靜態變量分配空間,且賦予默認的初始值。

連接-解析:將class文件中符號引用轉變成直接引用。

初始化:爲類的靜態變量賦予正確的初始值,只有在類首次主動使用的時候,纔會進行初始化。

 

 

介紹一下JVM將何時結束線程的生命

(1)程序執行System.exit()

(2)程序正常結束

(3)程序拋出異常,一直向上拋出,沒有try{}catch()finally{}處理。

(4)由於操作系統的異常,導致JVM退出

 

jvm結構圖

 

 

 

單例模式的應用場景

1.共享資源配置的讀取

2.數據庫獲取連接,連接池原理

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章