程序員入職寶典:面試,你真的準備好了嗎?

1.1.1.祝你好運

準備換一份工作你的真的準備好了嗎,朋友送的一份面試資料,本文搞為初稿大致看過,有時間在持續修正更新

程序員入職寶典:面試,你真的準備好了嗎?

1.1.2. 開發流程

程序員入職寶典:面試,你真的準備好了嗎?

1.1.3. 併發

什麼是併發:所謂併發操作是指在同一時間可能有多個用戶對同一數據進行讀寫操作.

併發問題的瓶頸在哪兒,讀和寫。

怎麼解決併發:

所謂併發是指大量用戶同一時刻讀寫同一條數據,那關鍵點就在於讀和寫。

> 首先從讀的角度來解決:

1、讀寫分離。

2、配置緩存

3、配置集群

> 從寫的角度:

1、從項目的情況來選擇合適的隊列。

2、配置集群

在解決併發的時候可以舉一個形象的例子來闡述什麼是併發:比如我們去乘坐地鐵,如果不排隊是不是就很擠很亂,效率就低啊,那如果排隊之後一個一個來效率是不是就提高了,這樣就解決了大併發的問題。

那麼怎麼實現這個隊列呢,這就是我們需要考慮的問題,在 java 代碼中我們使用的 list集合是不是就是一個隊列,循環遍歷一個一個取出。而在 redis 中還有一種數據結構就是 list結構,這就是一個隊列結構。當然我們也可以將 MQ 作為一個方案,MQ 本來就是處理隊列的。怎麼取捨,就需要考慮到 redis 和 MQ 的優缺點,然後看需求了。

如果簡單點,就用以上回答.

> 詳細點見下:

1、確認服務器硬件是否足夠支持當前的容量。

普通的 P4 服務器一般最多能支持每天 10 萬獨立 IP,如果訪問量比這個還要大,那麼必須首先配置一臺更高性能的專用服務器才能解決問題,否則怎麼優化都不可能徹底解決性能問題。

2、優化數據庫訪問。

前臺實現完全的靜態化,可以完全不用訪問數據庫。不過對於頻繁更新的網站,靜態化往往不能滿足某些功能。緩存技術是另一個解決方案,將動態數據存儲到緩存文件中,動態網頁直接調用這些文件,而不必再訪問數據庫。如果確實無法避免對數據庫的訪問,那麼可以嘗試優化數據庫的查詢SQL.避免使用 Select *from 這樣的語句,每次查詢只返回自己需要的結果,避免短時間內的大量 SQL 查詢。

3、禁止外部的盜鏈。

外部網站的圖片或者文件盜鏈往往會帶來大量的負載壓力,因此應該嚴格限制外部對於自身的圖片或者文件盜鏈。好在目前可以簡單地通過 refer 來控制盜鏈,Apache 自己就可以通過配置來禁止盜鏈,IIS 也有一些第三方的 ISAPI 可以實現同樣的功能。或者使用非技術手段來解決,比如在圖片上增加水印。

4、控制大文件的下載。

大文件的下載會佔用很大的流量,並且對於非 SCSI 硬盤來說,大量文件下載會消耗 CPU,使得網站響應能力下降。因此,儘量不要提供超過 2M 的大文件下載,如果需要提供,可以將大文件放在另外一臺服務器上。

5、使用不同主機分流主要流量

將文件放在不同的主機上,提供不同的鏡像供用戶下載。比如如果覺得 RSS 文件佔用流量大,那麼使用 FeedBurner 或者 FeedSky 等服務將 RSS 輸出放在其他主機上,這樣別人訪問的流量壓力就大多集中在 FeedBurner 的主機上,RSS 就不佔用太多資源了。

6、使用流量分析統計軟件。

在網站上安裝一個流量分析統計軟件,可以即時知道哪些地方耗費了大量流量,哪些頁面需要再進行優化。因此,解決流量問題還需要進行精確的統計分析才可以。推薦使用的流量分析統計軟件是Google Analytics(Google 分析)。

7、HTML 靜態化

效率最高、消耗最小的就是純靜態化的 html 頁面,所以我們儘可能使我們的網站上的頁面採用靜態頁面來實現,這個最簡單的方法其實也是最有效的方法。但是對於大量內容並且頻繁更新的網站,我們無法全部手動去挨個實現,於是出現了我們常見的信息發佈系統 CMS。信息發佈系統可以實現最簡單的信息錄入自動生成靜態頁面,還能具備頻道管理、權限管理、自動抓取等功能,對於一個大型網站來說,擁有一套高效、可管理的 CMS 是必不可少的。

8、圖片服務器分離

對於 Web 服務器來說,圖片是最消耗資源的,於是我們有必要將圖片與頁面進行分離,使用獨立的圖片服務器,甚至很多臺圖片服務器。這樣的架構可以降低提供頁面訪問請求的服務器系統壓力,並且可以保證系統不會因為圖片問題而崩潰。在應用服務器和圖片服務器上,可以進行不同的配置優化。

9、數據庫集群和庫表散列

我們在應用程序中按照業務和應用或者功能模塊將數據庫進行分離,不同的模塊對應不同的數據庫或者表,再按照一定的策略對某個頁面或者功能進行更小的數據庫散列,比如用戶表,按照用戶 ID進行表散列,這樣就能夠低成本的提升系統的性能並且有很好的擴展性。

1.1.4. 集群

其實從上面併發的地鐵例子,還可以牽扯出另外一個方案,集群。所謂集群其實就相當於我多開了幾個收銀櫃臺。那麼比如我開放了 10 個進票口,不管我之後可能幾個進票口可能出現問題,只要還有一個在正常工作就可以。

1.1.5. 分佈式

> 分佈式架構,我們必須對比傳統架構才能彰顯其優勢

①最為明顯的一點,在傳統的架構中,如果某個功能需要進行維護,那麼我們必須停掉整個服務,這對於公司的運營會造成損失。分佈式系統在核心功能模塊使用單獨服務器,維護部分模塊不影響用戶的其他操作。

②在海量數據處理方面,傳統架構顯得比較乏力;分佈式系統架構採用服務器集群,使用負載均衡,海量數據處理遊刃有餘!

③在性能(檢索)以及維護方面,分佈式系統架構也有較為明顯的優勢。而所謂的分佈式,其實也可以用地鐵來舉例子。地鐵進票口和門口的包裹檢查,這是兩個系統,進票口和包裹檢查這是兩個模塊,互不幹,這個就是分佈式。兩個系統做各自的事情,但是事情是有聯繫的,組合起來就是一個完整的流程。而且任何一方如果需要維護,並不影響另外一方的運行。

1.1.6. 多線程

1.1.6.1.線程池

創建線程是比較耗費資源的,這時就有了線程池的引入。

線程池是指在初始化一個多線程應用程序過程中創建一個線程集合,然後在需要執行新的任務時重用這些線程而不是新建一個線程。

線程池的概念類似連接池。

線程池能夠帶來三個好處。

第一:降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的消耗。

第二:提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。

第三:提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性

1.1.6.2.java 多線程解決方案

synchronized 關鍵字主要解決多線程共享數據同步問題,ThreadLocal 主要解決多線程中數據因併發產生不一致問題,二者都用於解決多線程併發訪問。

二者的本質區別:

synchronized 是利用鎖的機制,使變量或代碼在某一時刻只能被一個線程訪問。而

ThreadLocal 為每一個線程都提供了變量的副本,使得每個線程在某一時間訪問到的並不是同一個對象,這樣就隔離了多個線程對數據的共享。而 synchronized 正好相反,它用於在多個線程間共享通信時能夠數據共享。synchronized 用於線程間數據共享,而 ThreadLocal 用於線程間數據隔離。

1.1.6.3.什麼叫線程死鎖?

兩個或者多個線程之間相互等待使用對方的鎖,導致線程都無法執行,叫做線程死鎖。

1.1.6.4.請描述一下進程與線程的區別?

進程和線程的主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變量的併發操作,只能用線程,不能用進程。

1) 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.

2) 線程的劃分尺度小於進程,使得多線程程序的併發性高。

3) 另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。

4) 線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

5) 從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

1.1.6.5.現在有 T1、T2、T3 三個線程,如何保證 T2 在 T1 執行完後執行,T3 在 T2 執行完後執行?

在 JDK1.5 中,提供了 Condition 對象控制線程狀態,可以有針對性的控制線程的等待和喚醒Condition 對象可以創建多個,每個 Condition 可以控制不同類型的線程。這樣就能實現讓指定類型線程等待或喚醒!

例如:我們可以創建兩個 Condition,一個控制生成線程,一個專門控制消費線程!

1.1.6.6.wait 和 sleep 方法有什麼區別:

wait 需要使用 notify 或 notifyAll 喚醒,而 sleep 方法它時間到會自動醒。

wait 需要放在同步代碼塊中。sleep 可以在同步中也可以不在同步中。

wait 在等待的時候會釋放鎖,sleep 不會釋放鎖。

wait 可以指定時間也可以不指定時間,但 sleep 必須指定時間。

1.1.7. 權限

一般企業中權限控制有哪幾種方式:

1、創建文件夾,將需要控制的相應文件放在該文件夾下,通過判斷文件夾名稱來控制權限

2、通過 url 地址進行控制,在用戶表中添加一列,在這列中添加可以訪問的所有路徑

3、配置文件管理權限,通過針對不同的角色創建不同的文件,在文件中添加用戶可以訪問的路徑,然後通過配置過濾器來設置權限

4、利用 Spring Security 或者 shiro 等框架實現權限管理

Shiro:

支持認證跨一個或多個數據源(LDAP,JDBC,kerberos 身份等)

執行授權,基於角色的細粒度的權限控制。

增強的緩存的支持。

支持 web 或者非 web 環境,可以在任何單點登錄(SSO)或集群分佈式會話中使用。

主要功能是:認證,授權,會話管理和加密。

Spring Security:

這是一種基於 Spring AOP 和 Servlet 過濾器的安全框架。它提供全面的安全性解決方案,同時在 Web 請求級和方法調用級處理身份確認和授權。在 Spring Framework 基礎上,Spring Security 充分利用了依賴注入(DI,Dependency Injection)和麵向切面技術。

1.1.8. 網站併發量

Nginx 的併發量大致在 3-5 萬。

1.1.9. 訂單 ID 是怎麼生成的?

訂單 ID 首先是不能重複的,鑑於此,我們可以使用商品 ID+當前時間戳,或者通過userId+當前時間戳通過 MD5 加密的方式,來獲取一個唯一的訂單號,主要還是看需求,並保證訂單 ID 的唯一性。

1.1.10. 如果用戶一直向購物車添加商品怎麼辦?並且他添加一次你查詢一次數據庫?互聯網上用戶那麼多,這樣會對數據庫造成很大壓力你怎麼辦?

配置讀寫分離,講數據庫分成讀庫和寫庫,當查詢數據的時候從讀庫中進行查詢,並且可以添加緩存,利用緩存來提高讀取效率,增刪改操作就使用寫庫。這樣就能很大程度上緩解數據庫的壓力。

1.1.11. 項目是分佈式的,系統與系統之前如何進行通訊。

通信協議和技術有很多,如 web service,EJB,jms,httpclient.

1.2. 框架面試問題

1.2.1. Servlet

通過判斷客戶端發送的請求是 post 還是 get 方法來確定執行的是 doGet 還是 doPost 方法

Servlet 生命週期:

1、創建時間:當這個 Servlet 程序被外界第一次訪問的時候 tomcat 服務器內部會自動的創建這個 Servlet 對象,並調用 init 方法對這個 Servlet 進行初始化

2、服務的時間:當 Servlet 創建初始化完成之後,就開始一直在提供服務,用戶通過瀏覽器只要訪問這個 Servlet 程序,那麼就一定會調用這個 Servlet 的 service 方法。每次訪問都會調用 service 方法。Servlet 中的 service 方法是專門提供出來給用戶服務的。

3、銷燬的時間:當這個 Servlet 從項目中被移除,或者 tomcat 服務器正常關閉(需要手動的去使用 stoptomcat),才會調用。

1.2.2. Struts

Struts 是一個按 MVC 設計的 web 層的框架,其實它就是一個更大的 servlet,這個 servlet 是

ActionServlet 或者 ActionServlet 的子類,說到底就是把 servlet 給封裝了。

Struts 執行流程:

1)客戶端提起一個請求

2)這個請求經過一系列的過濾器直到最後一個過濾器 FilterDispatcher(Filter)

3)接著 FilterDispatcher 被調用,FilterDispatcher 詢問 ActionMapper 來決定這個請是否需要調用某個 Action

4)如果 ActionMapper 決定需要調用某個 Action,FilterDispatcher 把請求的處理交給ActionProxy

5)ActionProxy 通過 Configuration Manager 詢問框架的配置文件,找到需要調用的Action 類

6)ActionProxy 創建一個 ActionInvocation 的實例。

7)ActionInvocation 實例使用命名模式來調用,在調用 Action 的過程前後,涉及到相關攔截器(Intercepter)的調用。

8)一旦 Action 執行完畢,ActionInvocation 負責根據 struts.xml 中的配置找到對應的返回結果

優點:

1、實現 MVC 模式,結構清晰,開發者只關注業務邏輯的實現。

2、Strust 的標籤庫提供了豐富的標籤可以使用,大大提高了開發效率

3、頁面導航:通過一個配置文件,即可把握整個系統各部分之間的聯繫。

4、提供了 exception 處理機制

5、數據庫連接池管理

6、支持 I18N

缺點:

1、Struts 對每一個用戶的請求都會創建一個 action,它只允許一個實例去處理所有的請求。

2、測試不方便,struts 的每一個 action 都和 web 層耦合在一起,它的測試依賴於 web 容

器,單元測試也很難,不過有一個 Junit 的擴展工具 Struts TestCase 可以實現單元測試。

3、對Servlet依賴性過強,Structs處理action都必須依賴ServletRequest和ServletResponse,擺脫不了 servlet 容器。

Struts 和 springmvc 的區別:

1、springMVC 的入口是 Servlet,Struts2 的入口是 Filter,兩者的實現機制不同

2、SpringMVC 是基於方法設計,傳遞參數是通過方法形參接收,其實現方式是單例設計模式(也可以改為多例,推薦使用單例),

Struts2 是基於類設計,傳遞參數是通過類的屬性,只能是多例實現,性能上 springMVC更高一些

4、傳遞參數方面,Struts2 是用類的屬性來接收,也就是在多個方法間共享,而 springMVC是基於方法的,多個方法間數據無法共享

5、Struts 是類級別的攔截,一個類對應一個 request 上下文,而 springmvc 是方法級別的攔截,一個方法對應一個 request 上下文,而一個方法又對應一個 url,因此從架構上來說springmvc 更容易實現 restful。

1.2.3. Springmvc

Springmvc 執行流程:

程序員入職寶典:面試,你真的準備好了嗎?

1. 用戶向服務器發送請求,請求被 Spring 前端控制 Servelt ---DispatcherServlet 捕獲;

2. DispatcherServlet 對請求 URL 進行解析,得到請求資源標識符(URI)。然後根據該 URI,調用 HandlerMapping 獲得該 Handler 配置的所有相關的對象(包括Handler 對象以及 Handler 對象對應的攔截器),最後以 HandlerExecutionChain 對象的形式返回;

3. DispatcherServlet 根據獲得的 Handler,選擇一個合適的 HandlerAdapter。(附註:如果成功獲得 HandlerAdapter 後,此時將開始執行攔截器的 preHandler(...)方法)

4. 提取 Request 中的模型數據,填充 Handler 入參,開始執行 Handler(Controller)。 在填充 Handler 的入參過程中,根據你的配置,Spring 將幫你做一些

額外的工作:

HttpMessageConveter: 將請求消息(如 Json、xml 等數據)轉換成一個對

象,將對象轉換為指定的響應信息

數據轉換:對請求消息進行數據轉換。如 String 轉換成 Integer、Double 等

數據根式化:對請求消息進行數據格式化。 如將字符串轉換成格式化數字或格式化日期等

數據驗證: 驗證數據的有效性(長度、格式等),驗證結果存儲到 BindingResult或 Error 中

5. Handler 執行完成後,向 DispatcherServlet 返回一個 ModelAndView 對象;

6. 根據返回的 ModelAndView,選擇一個適合的 ViewResolver(必須是已經註冊到Spring 容器中的 ViewResolver)返回給 DispatcherServlet ;

7. ViewResolver 結合 Model 和 View,來渲染視圖

8. 將渲染結果返回給客戶端。

1.2.4. Hibernate

優點:

對象/關係數據庫映射(ORM),使用時只需要操作對象,完全面向對象的思想。

封裝了 jdbc 的底層代碼,不需要和 jdbc api 打交道即可直接訪問數據庫,在大型項目中開發效率高。

封裝了很多可操作數據庫的方法,不需要寫 sql 語句。

提供一二級緩存。

缺點:

執行效率低,很多 sql 語句都是自動生成的,會有冗餘語句,優化負責,更消耗內存。

多表和複雜數據的操作比較麻煩。

更適合單一對象的操作,不適合批量操作。

和 mybatis 的比較:

1、MyBatis 容易掌握,而 Hibernate 門檻較高。

2、Mybatis 基於原生的 jdbc,運行速度比 hinernate 更高。

3、針對高級查詢,Mybatis 需要手動編寫 SQL 語句,以及 ResultMap。而 Hibernate 有良好的映射機制,開發者無需關心 SQL 的生成與結果映射,可以更專注於業務流程。

4、Hibernate 數據庫移植性很好,MyBatis 的數據庫移植性不好,不同的數據庫需要寫不同 SQL。

1.2.5. Spring

Spring IOC:

所謂控制反轉,舉個例子:

遵循 mvc 的開發原則,我們在 web 層創建業務層對象時如下:

UserService userService=new UserService ();

但是這樣寫死的話不利於擴展和維護。而為了利於擴展功能,因此我們會寫一個接口比如 userService,然後再通過父類引用子類對象的多態原則使程序有更好的擴展性:

UserService userService=new UserServiceImpl().但這種寫法還是耦合性太高,如果有一天我要更換實現類,還是需要修改原代碼,這樣就違法了 OCP 原則(open-close 原則,該原則建議不要修改原代碼,可以通過添加新的代碼,實現新的功能,即對修改關閉,對擴展開放)。

那麼為了實現 service 層和 web 層的解耦,我們就使用了工廠方式:

程序員入職寶典:面試,你真的準備好了嗎?

但是如此一來,工廠和實現類又耦合了,那麼是否可以使工廠和實現類解耦呢。可以通過反射和配置文件:

程序員入職寶典:面試,你真的準備好了嗎?

而 IOC 能做到什麼呢,就是 service 不再利用 web 層去獲取,而是通過 spring 容器創建bean 對象來自動的為我們注入。這樣的話整個過程就反過來了,以前是 web 層去 new 一個service,現在是 service 主動被設置到 web 層中去了,這就是反轉控制的由來。

通過 IOC,我們就可以在不修改任何代碼的情況下,就可以進行實現類的切換,當然前提還是必須得寫一個 service 的實現類。這樣我們只需要在配置文件配置一下就 ok 了,而不需要再一個個的寫工廠來獲取了。

這就是 IOC 為我們帶來的模塊的松耦合和應用的便利性。

DI 注入:

依賴注入,在 spring 框架創建 bean 對象時,動態的動態的將依賴對象注入到 bean 組件。

舉例:HelloServiceImpl 內部需要依賴 info 屬性

程序員入職寶典:面試,你真的準備好了嗎?

傳統方法和依賴注入的區別:

程序員入職寶典:面試,你真的準備好了嗎?

IOC 和 DI 的區別:

IOC 控制反轉指的是對象的創建權,被反轉到了 spring 容器來管理。DI 依賴注入,指spring 容器在創建對象的過程中將對象依賴的屬性通過配置文件進行注入。表面是先有控制反轉,再有依賴注入。實際是一個事件,兩種不同時期的稱呼。DI 實際上也可以理解為就是實現 IOC 的方式。就比如將一個 B 對象注入到另外一個 A對象中,即實現了控制反轉(不再在 A 對象中創建 B 對象,而是通過配置文件主動配置),也實現了 DI 注入(將 B 對象作為 A 對象的屬性,利用配置文件注入到 A 對象中)。

Spring AOP:

AOP 的意思就是面向切面編程,AOP 採取橫向抽取機制,取代了傳統縱向繼承體系重複性代碼。實際上就是利用動態代理對目標對象中的方法進行增強JDK 的動態代理要求被代理對象必須實現接口。Cglib 則不需要。AOP 的底層實際上是實現了 JDK 和 CGLIB 兩種代理機制。如果目標對象實現了接口,那麼優先使用 JDK 的動態代理,如果沒有實現任何接口,就會使用 CGLIB 庫生成目標對象的子類作為代理對象。

1.3. 數據庫面試問題

1.3.1. Mysql 的數據庫引擎

Innodb 引擎

Innodb 引擎提供了對數據庫 ACID 事務的支持,並且實現了 SQL 標準的四種隔離級別,關於數據庫事務與其隔離級別的內容請見數據庫事務與其隔離級別這篇文章。該引擎還提供了行級鎖和外鍵約束,它的設計目標是處理大容量數據庫系統,它本身其實就是基於 MySQL 後臺的完整數據庫系統,MySQL 運行時 Innodb 會在內存中建立緩衝池,用於緩衝數據和索引。但是該引擎不支持 FULLTEXT 類型的索引,而且它沒有保存表的行數,當SELECT COUNT(*) FROM TABLE 時需要掃描全表。當需要使用數據庫事務時,該引擎當然是首選。由於鎖的粒度更小,寫操作不會鎖定全表,所以在併發較高時,使用 Innodb 引擎會提升效率。但是使用行級鎖也不是絕對的,如果在執行一個 SQL 語句時 MySQL 不能確定要掃描的範圍,InnoDB 表同樣會鎖全表。

MyIASM 引擎

MyIASM 是 MySQL 默認的引擎,但是它沒有提供對數據庫事務的支持,也不支持行級鎖和外鍵,因此當 INSERT(插入)或 UPDATE(更新)數據時即寫操作需要鎖定整個表,效率便會低一些。不過和 Innodb 不同,MyIASM 中存儲了表的行數,於是 SELECT COUNT(*)FROM TABLE 時只需要直接讀取已經保存好的值而不需要進行全表掃描。如果表的讀操作遠遠多於寫操作且不需要數據庫事務的支持,那麼 MyIASM 也是很好的選擇。兩種引擎的選擇大尺寸的數據集趨向於選擇 InnoDB 引擎,因為它支持事務處理和故障恢復。數據庫的大小決定了故障恢復的時間長短,InnoDB 可以利用事務日誌進行數據恢復,這會比較快。主鍵查詢在 InnoDB 引擎下也會相當快,不過需要注意的是如果主鍵太長也會導致性能問題,關於這個問題我會在下文中講到。大批的 INSERT 語句(在每個 INSERT 語句中寫入多行,批量插入)在 MyISAM 下會快一些,但是 UPDATE 語句在 InnoDB 下則會更快一些,尤其是在併發量大的時候。

1.3.2. SQL 優化

1. 對操作符的優化 儘量不採用不利用索引的操作符

如:in ,not in , is null, is not null,<> like 等

2. select count(*) from table;這樣不帶任何條件的 count 會引起全表掃描,並且沒有任何

業務意義,是一定要杜絕的。

3. 使用“臨時表”暫存中間結果

部分 UPDATE、SELECT 語句 寫得很複雜(經常嵌套多級子查詢)——可以考慮適當拆成幾步,先生成一些臨時數據表,再進行關聯操作。簡化 SQL 語句的重要方法就是採用臨時表暫存中間結果,但是,臨時表的好處遠遠不止這些,將臨時結果暫存在臨時表,後面的查詢就在 tempdb 中了,這可以避免程序中多次掃描主表,也大大減少了程序執行中“共享鎖”阻塞“更新鎖”,減少了阻塞,提高了併發性能。

4. 排序

避免使用耗費資源的操作,帶有 DISTINCT,UNION,MINUS,INTERSECT,ORDER BY 的 SQL語句會啟動 SQL 引擎 執行,耗費資源的排序(SORT)功能. DISTINCT 需要一次排序操作,而其他的至少需要執行兩次排序

1.3.3. 如何快速向表中插入 100 萬條數據

1、Mysql 中有 LOAD DATA INFILE 語句用於高速地從一個文本文件中讀取行,並裝入一個表中。文件名稱必須為一個文字字符串。

2、批量插入

程序員入職寶典:面試,你真的準備好了嗎?

1.4. java 基礎

1.4.1. Error 和 Exception 的區別

Error:表示 Java 程序中存在的那些錯誤現象,而這些錯誤現象統一使用 Error 進行描述。在我們的程序中,如果發生 Error 問題,我們不會去處理這樣的問題,而是讓程序的定義者自己去處理自己程序中的錯誤。針對 Error 我們不給出程序的針對性處理。

Exception:表示 Java 程序中存在的異常問題。而不是錯誤問題。而這些異常問題,在程序中通過

判斷等形式是可以檢測並且預防的。而針對這些異常問題,程序員在寫代碼的時候一旦發生必須給出有效的解決方案。

1.4.2. 垃圾回收器的基本原理是什麼?垃圾回收器可以馬上回收內存嗎?有什麼方法可以通知 jvm 進行垃圾回收?

答:對象剛創建,GC 就開始監控這個對象的地址、大小以及使用情況。通常,GC 採用有向圖的方式記錄和管理(heap)堆中所有對象。通過這種方式確定哪些對象時可達的,哪些是不可達的,當確定一些對象不可達,GC 就有責任回收這些內存空間。可以。手動執行 System.gc(),通知 GC 運行,但是 java 語言規範並不保證 gc 一定運行。

1.4.3. 抽象類和接口的區別?什麼時候用抽象類,什麼時候用接口?

答:

含有 abstract 修飾符的類就是抽象類,抽象類不能創建實例對象。含有抽象方法的類必須是抽象類,抽象類中可以有非抽象方法。

子類在繼承抽象類時,必須重寫抽象類的所有抽象方法。不能有抽象構造方法和抽象靜態方法。如果子類沒有實現抽象類中的所有抽象方法,那麼子類也必須是抽象的。

接口是抽象類的一種特例,接口中的方法都是抽象方法,接口中的變量都要用 public static final 修飾。

兩者的區別:

1.抽象類中可以有構造方法,接口中沒有構造方法

2.抽象類中有普通的成員變量,接口中沒有普通成員變量。

3.抽象類中可以有非抽象方法,接口中不能有非抽象方法。

4.抽象類中抽象方法的訪問類型可以是 public ,protected,但是接口中只能是 public

5.抽象類中可以有靜態方法,接口中不能有靜態方法。

6.抽象類和接口中都可以包含靜態成員變量,抽象類中的靜態成員變量的訪問類型可以任意,

但是接口中必須是 public static fianl。

7.一個類可以實現多個接口,但是隻能繼承一個抽象類

應用上的不同:

接口更多的是在系統架構設計方法上發揮作用,主要用於定義模塊之間的通信契約和擴展功能。

而抽象類在代碼實現方面發揮作用,可以實現代碼的重用。比如我們項目中三層開發中的 dao 層和 service 層,會創建一個接口,然後定義一個接口類,主要是考慮到多實現。

在 mybatis 的時候,我們操作數據庫,會封裝一些方法到一個抽象類中,然後由 service 層來繼承這個抽象類,就可以複用裡面的方法,方便開發。

1.4.4. 是否可以繼承 String 類?

不可以,因為 String 類被 final 修飾。

1.4.5. String 和 StringBuffer 的區別?

1.String 數值不可變,StringBuffer 字符串長度可變。

2.String 覆蓋了 equals 和 hashCode 方法,StringBuffer 沒有覆蓋 equals 和 hashCode 方法。

1.4.6. final、finalize 和 finally 的區別

final 用於聲明屬性,方法和類的

finally 是異常處理語句結夠的一部分,表示總是執行。

finalize 是 Object 類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法

1.4.7. 多線程有幾種實現方法?同步有幾種實現方法?

多線程有兩種實現方法:繼承 Thread 類和實現 Runnable 接口。

1.4.8. 簡述一下線程的幾種可用狀態;

線程在執行過程中,可以處於下面幾種狀態:

1、就緒(Runnable):線程準備運行,不一定立馬就能開始執行。

2、運行中(Running):進程正在執行線程的代碼。

3、等待中(Waiting):線程處於阻塞的狀態,等待外部的處理結束。,

4、睡眠中(Sleeping):線程被強制睡眠。

5、I/O 阻塞(BlockedonI/O):等待 I/O 操作完成。

6、同步阻塞(BlockedonSynchronization):等待獲取鎖。

7、死亡(Dead):線程完成了執行。

1.4.9. 什麼是 java 序列化,如何實現 java 序列化?或者請解釋 serializable 的作用.

序列化:就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化後的對象進行讀寫操作,也可將流化後的對象傳輸於網絡之間。序列化是為了解決在對對象流進行讀寫操作時所引發的問題。

序列化的實現:將需要被序列化的類實現 Serializable 接口,然後使用一個輸出(如:FileOutputStream)來構造一個 ObjectOutputStream(對象流)對象,接著使用 ObjectOutputStream 對象的writeObject(Object obj)方 法就 可以 將參數 為 obj 的 對象 寫出(即 保存其 狀態), 要恢 復的話則 用輸 入流ObjectInputStream。

1.4.10. session 共享的幾種方式?

1.寫客戶端 cookie 的方式

當用戶登陸成功以後,把網站域名、用戶名、密碼、token、session 有效時間全部採用 cookie的形式寫入到客戶端的 cookie 裡面,如果用戶從一臺 Web 服務器跨越到另一臺服務器,我們的程序主動去檢測客戶端的 cookie信息,進行判斷,然後提供對應的服務。當然,如果 cookie 過期或者無效,自然就不讓用戶繼續服務了。當然,這種方法的弊端就不言而喻了,比如客戶端禁用了cookie 或者 cookie 被黑客竊取了呢?

2.服務器之間 Session 數據同步的方式

假設 Web 服務器 A 是所有用戶登陸的服務器,那麼當用戶驗證登陸一下,session 數據就會寫到 A 服務器裡,那麼就可以自己寫腳本或者守護進程來自動把 session 數據同步到其他 Web 服務器,那麼當用戶跳轉到其他服務器的時候,那麼 session 數據是一致的,自然就能夠直接進行服務無須再次登陸了。缺點是,可能會速度慢,不穩定。如果是單向同步的話,登陸服務器出現問題,那麼其他服務器也無法服務,當然也可以考慮雙向同步的問題。

3.利用 NFS 共享 Session 數據的方式

大致就是有一臺公共的 NFS 服務器(Network File Server)做共享服務器,所有的 Web 服務器登陸的時候把 session 數據寫到這臺服務器上,那麼所有的 session 數據其實都是保存在這臺 NFS 服務器上的,不論用戶訪問哪臺 Web 服務器,都要來這臺服務器獲取 session 數據,那麼就能夠實現共享 session 數據了。缺點是依賴性太強,如果 NFS 服務器掛掉了,那麼大家都無法工作了。當然,可以考慮多臺 NFS 服務器同步的形式。

4. 利用 Mysql 數據庫共享 Session 數據的方式(我們可以使用 Redis)

這個方式與 NFS 的方式類似,也是採用一臺 Mysql 服務器做共享服務器,把所有的 session的數據保存到 Mysql 服務器上,所有 Web 服務器都來這臺 Mysql 服務器來獲取 Session 數據。缺點也是依賴性太強,Mysql無法工作了影響所有的 Web 服務器。當然,可以考慮多臺 Mysql 數據庫來共享 session,使用同步 Mysql 數據的方式。

5.使用硬件設備

這個算是比較成熟的解決方案了,使用類似 BIG-IP 的負載設備來實現資源共享,那麼就能夠又穩定又合理的的共享 Session 了。目前很多門戶網站採用這種方式。缺點很明顯了,就是要收費了,硬件設備肯定需要購買成本的,不過對於專業或者大型應用來講,是比較合理並且值得的

1.4.11. Ajax 同步與異步的區別

異步傳輸方式是用的最多的也是默認的方式,他避免了服務器檢索給用戶帶來的時間延遲。在異步傳輸時候,它只是在後面悄悄進行著,用戶仍舊可以做他做的事情,不會給用戶任何的等待的感覺。在傳輸的數據量較大的時候,服務器檢索的時間就更長了,但是用戶卻不知道,用戶仍舊專注於頁面上面的操作,根本就不知道服務器都幹了些什麼,就給用戶良好的體驗。同步傳輸方式卻相反,他就好像是剛剛加載頁面的那一刻一樣,當發出了同步請求之後,瀏覽器就在等待,等待服務器檢索完畢,返回結果。此時,鼠標會變成等待的形狀,提醒我們的用戶請求還沒有相應,您什麼也不能做,我們的用戶就什麼也幹不成,能夠做的一件事就是——等待……雖然用戶已經習慣了等待整改頁面的加載,雖然在 ajax 裡面同步請求的時間一般不會大於整個頁面加載的時間,但是你要知道什麼都不做只是在那裡被動等待是多麼痛苦的一件事情。所以,這個同步請求要慎重使用……

1.4.12. 簡單描述一下 List、Map 和 Set 的區別;

1.Set 接口:有兩個實現類(HashSet(底層由 HashMap 實現),LinkedHashSet)

2.List 接口:有三個實現類(LinkedList:基於鏈表實現,鏈表內存是散亂的,每一個元素存儲本身內存地址的同時還存儲下一個元素的地址。鏈表增刪快,查找慢;

ArrayList:非線程安全的,效率高;基於數組;便於索引,但不便於插入刪除

Vector:基於線程安全的,效率低;基於數組; )

3.Map 接口:有三個實現類(HashMap,HashTable,LinkedHashMap,TreeMap)

HashMap:非線程安全,高效,支持 null;

HashTable:線程安全,低效,不支持 null;

LinkedHashMap:非線程安全,是 HashMap 的一個子類,保存了記錄的插入順序

TreeMap:該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的 Comparator 進行排序

1.4.13. JAVA 中的方法覆蓋(Overriding)和方法重載(Overloading)是什麼意思?

覆蓋是 override 方法-重寫 重載是 overload按照教科書上的定義,重載就是具有相同函數名,返回類型可以不同,參數個數、順序、類型不同的函數。我的理解是重載是發生在兩個或者是更多的函數具有相同的名字的情況下。

重寫就是覆蓋父類的方法,和父類有相同返回類型,參數,甚至是拋出的異常,重寫方法不能為 private,運用中最典型的就是對接口方法的覆蓋。

我自己是一名從事了5年大數據挖掘,分析開發的工程師,辭職目前在做線上教育講師,創了一個交流 裙,每晚都會在 裙 內直播,今年年初我花了一個月整理了一份最適合2018年學習的大數據乾貨,包括數據採集。數據存儲和管理。數據處理和分析。數據隱私和安全。雲安全,雲技術,人工智能等資料都有整理,送給每一位大數據小夥伴,這裡是大數據學習者聚集地,歡迎初學和進階中的小夥伴。關注小編頭條號,私信【學習】即可免費領取本文全套資料!


分享到:


相關文章: