A. java和其他語言非同步SOCKET的問題
你需要補充自己的答案:你遠程管理伺服器可以在不重新啟動它嗎?您ulimit-a命令,當您每次啟動tomcat,把打開的文??件的最大數量值設置為
的/ proc / sys目錄/ FS /文件放到tomcat的啟動腳本最大限制的總的系統,在sysctl.conf中決定。
獲得的價值的ulimit當前用戶打開的文件(包括套接字連接)允許的最大數量
使用ulimit-n命令目前只用於當前登錄的後的值用戶有效的系統重新啟動或用戶出口將失敗。
如果你需要一個永久的,可以在/ etc / security / limits.conf中
格式說明符這個文件中的參數更詳細的,如果你想設置為4096,您可以添加以下內容:
*軟NOFILE 4096
*硬碟NOFILE 4096
如果你使用Linux的RedHat8的或9,在/ etc / pam.d / login文件登錄文件中添加以下行
會議要求/ lib / security中/是pam_limits.so
或
會議要求在pam_limits.so
B. JAVA培訓的都學一些什麼
目前Java培訓內容包括:
1、HTML+CSS3+資料庫
2、Java SE(Java面向對象思想;設計模式、面向對象原則、Java高階API、線程、網路編程、反射、NIO)
3、Java web(Java web基礎、JS、DOM操作、JSP/Servlet、第三方工具包、Tomcat...)
4、框架(網路原理、HTTP協議、Linux操作系統、雲服務搭建、SSM框架應用、Oracle應用、Spring JPA、Hibernate...)
5、高可用、高並發、高擴展(SpringBoot、緩存、分布式、插件、全文索引、服務中間件、消息中間件、雲伺服器、雲存儲、雲資料庫、域名服務...)
6、微服務、大數據
以下是我們2020年更新的課程,您可以了解一下!
如想學習,可在我們官網了解詳情。
如果想要自學,可私信我獲取學習資料。免費提供
希望我的回答對你有所幫助,望採納~
C. 如何一步一步學習java 知乎
兄弟連JavaEE戰狼班:
第一階段:Java語言基礎
★ Java語言基礎
1、面向對象思維JAVASE
2、(類載入機制與反射,annotation,泛型,網路編程,多線程,IO,異常處理,常用API,面向對象,JAVA編程基礎)
3、Java8新特性
第二階段:資料庫
★ 資料庫
1、Oracle(SQL語句、SQL語句原理、SQL語句優化、表、視圖
2、序列、索引、Oracle數據字典、Oracle 資料庫PL/SQL開發
3、資料庫設計原則、 MySQL 、 JDBC
第三階段:Web基礎
★ Web基礎
1、HTML5(H5)基本文檔結構、鏈接、列表、表格、表單;
2、CSS 基礎語法、盒子模型、浮動布局、定位;
3、JavaScript語言基礎、DOM 編程、事件模型等),JQuery,AJAX框架,XML,BootStrap組件
第四階段:Java Web技術和主流框架
★ Java Web技術和主流框架
1、JSP&Servlet、struts2,hibernate4,spring4,JPA,maven
2、SpringData,SpringMVC,MyBatis,SpringSecurity,shiro,Nginx
第五階段:Linux
★ Linux
1、Linux安裝、熟悉Linux的基礎命令、vi編輯器的使用、awk和sed命令使用、用戶和組
2、文件及目錄許可權管理、使用ACL進行高級訪問控制、網路配置和軟體包安裝、啟動流程和服務管理
3、系統監控和日誌管理、進程管理和計劃任務、ssh遠程登錄、shell基礎和shell腳本。
第六階段:大數據技術(Hadoop和Spark)
★ 大數據技術(Hadoop和Spark)
1、Hadoop (Hadoop基礎和環境搭建,HDFS體系結構,MapRece;Hadoop的集群模式、HDFS聯盟,利用ZooKeeper來實現Hadoop集群的HA(高可用性)功能
2、Yarn的任務調度機制,Apache Hive,Pig數據處理,集成Hadoop和Sqoop
3、Flume以及Apache Kafka來實現數據的交換,安裝部署HBase,Storm)
4、Scala 語言(Scala環境搭建、Scala基礎語法、模式匹配、重載與構造器、Map與rece、元組、繼承、StringContext,Option Some None,Tuple;集合方法和運算,future 對象同步處理和非同步處理返回結果)
5、Spark(Spark搭建,Spark-shell 的使用,Spark-submit 提交應用, Spark的內核設計和實現,並對內核中的實現架構、運行原理進行詳細的講解;Spark生態體系中的各個組件,包括:Spark Core,Shark,Spark SQL和Spark Streaming等等)
第七階段:項目
★ 項目
1、China-UCSP 項目 SSM(Spring+SpringMVC+MyBatis)
2、用戶關系管理系統 S2SH+Maven+Nodejs+MySQL技術實戰開發
3、電子商務交易平台 S2SH+Maven+Shiro+Oracle
D. 如何快速學會java
如果你足夠聰明的話,看網上深入的java視頻,連續幾個月,必出徒。
E. 麻煩給完整編程
print('\n'.join(input('請輸入多種水果名稱:').strip().split()))
F. 請問高手!
EJB
中科永聯高級技術培訓中心(www.itise.com)
EJB (Enterprise JavaBean)是J2EE的一部分,定義了一個用於開發基於組件的企業多重應用程序的標准。其特點包括網路服務支持和核心開發工具(SDK)。
在J2EE里,Enterprise Java Beans(EJB)稱為Java 企業柄,是Java的核心代碼,分為整體柄和片段柄和消息柄三個部分,其中的消息柄將在以後再作討論。現在我們來看看什麼是整體柄和片段柄。
整體柄是一種對象: 標准Java對象由創建它的程序創建,當程序終止時,對象也隨之丟失,這就意味著當再次運行些程序時,將無法找到先前創建的柄,而整體柄會一直存在著直到它被刪除。 一個程序可以創建一個整體柄,並且這個程序可以在被保存後隨時停止和重啟。整體柄將會依然存在。重啟後,程序可以找到與之相對應的整體柄,並且會繼續使用這個整體柄。
EJB實際上是SUN的J2EE中的一套規范,並且規定了一系列的API用來實現把EJB概念轉換成EJB產品.EJB是BEANS,BEANS是什麼概念,那就是得有一個容納她,讓她可勁造騰的地方,就是得有容器.EJB必須生存在EJB容器中.這個容器可是功能強大之極!她首先要包裝你BEAN,EJB的客戶程序實際上從來就不和你編寫的EJB直接打交道,他們之間是通過HOME/REMOTE介面來發生關系的.它負責你的BEAN的所有的吃喝拉薩睡,比如BEAN的持續化,安全性,事務管理...
一.什麼是 EJB?
一個技術規范:EJB 從技術上而言不是一種"產品"
EJB 是一種標准描述了構建應用組件要解決的:
可擴展 (Scalable)
分布式 (Distributed)
事務處理 (Transactional)
數據存儲 (Persistent)
安全性 (Secure)
二.Sun 對 EJB 的期望
提供一個標準的分布的、基於 OO 的組件架構
屏蔽復雜的系統級功能需求
Write once, run anywhere
與非 Java 應用之間的互操作能力
兼容 CORBA 標准
三.為什麼選擇 EJB?
EJB 伺服器完成"繁雜"的工作:應用開發人員關注於業務邏輯的實現而不是底層的實現機制(類似於 4GL 語言設計的目標)
支持事務處理
多個業務操作同時成功,或全部失敗
可以通過在代碼外的描述來定義事務處理級別
可擴展性
EJB 可以根據您應用的增長而擴展
EJB 伺服器往往還提供了負載均衡和
安全性:由 EJB 伺服器提供資源的訪問許可權控制
四.EJB 架構
為了滿足架構的目標,規范中描述了
伺服器 (Server)
容器 (Container)
類 (Class) 和實例 (Instance)
Home 和 Remote 介面
客戶端 (Client)
五. 簡化的編程模型
關注於業務邏輯實現:EJB 負責生命周期 (lifecycle), 數據存儲 (persistence), 事務處理語義 (transactional semantic), 安全(security), ...
通用的編程模型:各種服務的高層 API
Java 是其編程語言
1.EJB 特點
由一個 EJB 容器在運行時創建和管理 EJB
在部署 EJB 時定製其運行方式
由 EJB 容器和伺服器來協調客戶端的訪問
可以部署到任何兼容的 EJB 容器中
客戶端對 EJB 的視圖是由 Bean 開發人員決定的
2.EJB 伺服器
管理 EJB 容器 (它管理 Bean)
提供對操作系統服務的存取
提供 Java 相關的服務,尤其是
通過 JNDI 訪問命名空間
基於 OTS 的事務處理服務
3.EJB 容器
管理 Bean 生命周期:將 EJB 伺服器提供的服務傳遞給 Bean
生成代碼來實現對 Bean 的存取訪問
強制事務處理的限制
創建、初始化和回收 Bean
管理持久數據的存儲
對客戶端而言 EJB 容器是透明的
4.在一個 EJB 伺服器中的容器
目前容器通常是由 EJB 伺服器本身提供的
在 EJB 1.0 或 1.1 規范中沒有定義容器-到-伺服器的介面
各廠商可以根據他們的見解來實現伺服器和容器的各自責任
5.容器提供服務: 數據存儲
容器決定何時載入/儲存狀態
Container-Managed Persistence(容器管理存儲/CMP)
容器負責存儲您的 Bean
容器生成必要的類和代碼
Bean-Managed Persistence(Bean 管理存儲/BMP)
Bean 開發人員提供存儲代碼
開發人員決定 如何存儲, 容器仍然決定 何時進行
6.容器提供服務: 事務處理
可以由容器代理來實現
容器將得到業務邏輯方法的事務處理需求
容器提供事務控制代碼
也可以由程序員通過代碼實現
7.容器提供服務: 其它服務
其它服務包括
命名 (Naming)
安全 (Security)
線程管理 (Thread management)
這些服務由容器代理完成將減少應用開發人員的負擔
8.分布式對象運算
遠程對象被作為本地對象來處理:傳遞信息的方式不變,但開銷更大
Enterprise JavaBeans 永遠運行在伺服器上:對 Bean 的訪問永遠是遠程調用
9.Stub 和 Skeleton
由 EJB 生成:
"Stub" 對要傳遞出去的信息編碼
"Tie/Skel" 將接受到的信息解碼並傳遞給目標對象
10.分類: Enterprise JavaBeans
+---Entity Beans--CMP/BMP
Ejb--|
+---Session Beans--Stateful/Stateless
會話 Bean (Session Bean):根據 EJB 規范,一個會話 Bean 是:
代表單個客戶端來執行
可以參與到事務處理中
不直接代表共享於資料庫中的數據,但它能訪問和更新這些數據
相對而言是短暫存在的
當 EJB 容器失效後就不存在---客戶端需要重新建立一個信新的會話對象來繼續運算
實體 Bean (Entity Bean):根據 EJB 規范,一個實體 Bean 是:
提供在資料庫中數據的對象視圖
允許被多個用戶共享存取訪問
可以是長期存在 (只要它存在於資料庫中)
實體 Bean, 它的主鍵對象, 以及它的遠程引用將能跨 EJB 容器的宕機而存在
11.EJB 類和實例
構建 EJB 應用包括來自三方的代碼
開發人員編寫的代碼
由 EJB API 定義的類和介面
由容器自動生成的代碼
開發人員編寫的代碼包括
Bean 類 (定義了業務邏輯)
Home 介面 (如何查找或創建 bean)
Remote 介面 (如何存取 bean)
其它組件,根據 bean 實際要求
12.EJB Home 介面
每個 bean 有一個
用於:創建新的 bean 實例、查找現存的 bean (只能是實體 bean)
Remote 介面:定義 bean 的公共介面---只有在 Remote 介面中定義的方法才能被客戶端訪問
EJB 客戶端
可以為 servlet, JSP, 應用程序或其它 bean
通過 JNDI 來查找 EJB home 介面,步驟為:
創建一個 JNDI Context (initial context)
使用 JNDI Context 來查找 bean home 介面
使用 bean home 介面來創建/查找 bean 實例
使用 bean 實例完成業務操作
實際的存取 (對 EJB) 是通過容器生成的類來完成
EJB 架構
客戶端對 bean 訪問永遠不是直接的
EJBObject (tie) 是由容器自身提供的:用來幫助管理 bean 的生命周期
EJB 中的角色
EJB 伺服器供應商: 開發並銷售 EJB 伺服器
EJB 容器供應商: 開發並銷售 EJB 容器
Enterprise bean 開發人員: 開發並銷售 EJB
應用組裝人員: 將不同的 EJB 搭建成應用
六、EJB的體系結構
目前,EJB最新的標準是2.1,EJB3.0規范正在討論中,預計將於明年推出。EJB2.1定義了三種企業Bean,分別是會話Bean(Session Bean),實體Bean(Entity Bean)和消息驅動Bean(MessageDriven Bean)。
Session Bean用於實現業務邏輯,它可以是有狀態的,也可以是無狀態的。每當客戶端請求時,容器就會選擇一個Session Bean來為客戶端服務。Session Bean可以直接訪問資料庫,但更多時候,它會通過Entity Bean實現數據訪問。
Entity Bean是域模型對象,用於實現O/R映射,負責將資料庫中的表記錄映射為內存中的Entity對象,事實上,創建一個Entity Bean對象相當於新建一條記錄,刪除一個Entity Bean會同時從資料庫中刪除對應記錄,修改一個Entity Bean時,容器會自動將Entity Bean的狀態和資料庫同步。
MessageDriven Bean是EJB2.0中引入的新的企業Bean,它基於JMS消息,只能接收客戶端發送的JMS消息然後處理。MDB實際上是一個非同步的無狀態Session Bean,客戶端調用MDB後無需等待,立刻返回,MDB將非同步處理客戶請求。這適合於需要非同步處理請求的場合,比如訂單處理,這樣就能避免客戶端長時間的等待一個方法調用直到返回結果。
調用一個EJB組件要比調用一個JavaBean麻煩些,由於EJB組件可以分布在多台伺服器上,因此必須首先獲得遠程或本地Home介面,然後使用Home介面創建EJB之後就可以調用EJB的方法了。
七、EJB設計模式
常見EJB設計模式
SESsion Facade pattern
通常項目中,客戶端往往需要頻繁的對伺服器端數據進行操作。當採用實體EJB作為數據的抽象層時,如果直接讓客戶端程序與實體EJB交互,會產生實現一個業務需求便需要大量的EJB屬性操作(如下圖1)。這直接導致如下問題:網路負載大(遠程客戶端時)、並發性能低、客戶端與伺服器端關聯度大、可重用性和可維護性差、性能
因此有必要在客戶端與實體EJB層間加入Session EJB層,在Sessino EJB中實現商業邏輯並封裝對實體EJB的操作。(如下圖2)
圖1:客戶端直接與實體EJB交互
圖2:通過SessionEJB層實現
Session Facade模式的好處是:降低了網路負載,SessionEjb可以調用實體EJB的本地介面;將商業邏輯與商業數據隔離;維護與開發方便;顯著提高性能。
Session Facade模式因其簡單使用,是目前使用很廣的模式。但具體應用過程中應注意:避免將所有的操作封裝到一個很大的SessionEJB內;伺服器端數據結構應由實體EJB實現,除非特例否則避免直接的資料庫操作;SessionEjb內某些系統通用操作的代碼容易重復(比如許可權檢查等,解決辦法是將系統通用服務封裝在Java Class內)。
MesSAge Facade Pattern
很多時候,一次RequeST需要操作多個EJB又不需要得到即時返回。對這種非同步調用,通常應用Message Fa?ade Pattern.
這種時候,如採用Session Fa?ade Pattern存在如下問題:
1. 客戶端等待返回的時間過長。一個SessionEjb的實例在完成客戶請求過程中中涉及到的每一次對其他實體Ejb的調用過程中都會被鎖定直到得到實體EJB返回信息後才能進行下一步操作。這樣造成客戶不必要的等待,並很容易因時間導致整個事務失敗。
2. 系統可靠性和容錯性低。如果需要調用不同系統或伺服器上或多個異構數據源的多個EJB時,任何一個環節出錯,均導致客戶請求失敗。
以Message-Driven Bean為基礎的Message Facade Pattern則可以解決上述非同步請求需求。具體架構見下圖3
圖3:使用Message Facade Pattern
Message Facade Pattern的不足之處在於:
1. Message-Driven Bean沒有返回值。這樣通知客戶執行結果只能依賴於EmAIl或人工等其他手段。
2. Message-Driven Bean執行過程中無法將捕獲的異常直接返回給客戶端,即無法使客戶端直接直到錯誤信息。
3. Message-Driven Bean通過接收Message響應客戶請求,對Message內容的合法性(比如對象的類型等)依賴與客戶端.容易產生運行時錯誤。
Message Facade Pattern經常與Session Facade Pattern在同一個項目里共同使用。
EJB Command Pattern
Session Facade Pattern中將商業邏輯實現封裝在Session EJB中,這種做法帶來諸多益處之外也帶來如下問題:
1. 由於業務經常的變化,導致經常需要更新Session EJB代碼。
2. 客戶端代碼不得不包含大量EJB相關的API,不利於後期項目維護。
3. 項目開發測試需要經常的EJB重部署過程。
引起上述問題的重要根結就是Session EJB本身重量級組件,其開發測試部署工作量較大,開發周期較長。以上不足可以通過EJB Command Pattern克服。
EJB Command Pattern中將商業邏輯實現封裝在普通的Java ClASs(稱之為Command Bean)中。該模式的具體實現有很多種,通常的框架都包括三部分:
1. Command Bean.由應用開發者寫的具體實現某商業操作的Java Class.主要包含getXXX(),setXXX(),exECute()方法。
2. Client-Side Routing Logic.由多個Class組成,用於將請求轉發至Command Sever,這個過程對客戶是透明的。這部分代碼可以跨項目使用。路由規則中可以考慮用XML技術。
3. Remote Command Server.實際執行商業操作請求。通常可以用Session EJB層實現。
整個框架見下圖4:
圖4:Command的基本框架
EJB Command Pattern具有如下好處:
1. 適應與需要快速開發環境。因Command Bean是輕量級的Java Class,其編譯和調試比較方便。
2. 將表現層與商業實現層隔離,同時將客戶端代碼與EJB層隔離。
3. 將客戶端代碼開發與伺服器端代碼開發相對清晰。早期可以創建空的Command Bean方便客戶端代碼調試。
EJB Command Pattern的弱處在於:
1. Command Bean中對事務的控制不如Session EJB中。
2. Command Bean是無狀態的。
3. 無法將異常直接返回給客戶。
4. 在大項目中,由於商業邏輯復雜,常導致大數量的Command Bean存在.
5. 作為Command Server的Session EJB打包時必須包含Command Bean以致存在維護上的不便。
EJB Command Pattern的一個實際實現可以參考IBM's Command framework.
Data Transfer object Factory
基於EJB的J2EE項目,經常需要在客戶端與伺服器端傳輸大量數據。數據的組織形式常用的是DTO(Data Transfer Object,伺服器端數據對象的抽象)。但因為客戶端表現層經常是變化的,所需要伺服器端數據也變動頻繁,換句話說,DTO的數量和屬性經常要更改。因此如何以及在何處生成和維護DTO便是需要考慮的問題。
一種解決方案是直接在Entity EJB中直接處理,即在Entity EJB的Bean類中加入getXXXDTO()、setXXXDTO()等。但這樣做導致EJB與DTO層緊緊綁定。一旦DTO更改,與該DTO相關的EJB即需要重編譯打包。EJB層與客戶端層相關聯不僅使維護困難而且導致EJB的重用性大大降低。
更好的解決方案是利用Data Transfer Object Factory封裝對DTO的操作邏輯(如下圖6)。
圖6:DTO Factory示例
DTO Factory具體實現方式通常有兩種:
1. 普通Java Class實現,用於Session Facade Pattern使用DTO環境下。
2. Stateless Session EJB實現,用於非EJB客戶端使用DTO環境下(見圖7)。
圖7:SessionEJB實現DTOFactory
DTO Factory帶來如下好處:
1. 使Entity EJB的重用成為可能。由於不含DTO處理邏輯,Entity EJB功能單一化,只作為數據源。不通客戶端通過各自的DTO Factory可以從同一個Entity EJB得到各自所需的個性化數據(自定義DTO)。
2. 提高可維護性和性能。
3. 可以根據在DTO Factory層生成很復雜的DTO結構,諸如繼承、關聯關系等,而對客戶端提供一個透明、細化的數據介面。
使用DTO Factory時需要注意的是:不需為每個Entity EJB定義一個Factory。可以為一系列相關的Entity EJB創建一個Factory,或者只創建一個Factory。
Generic Attribute Access
使用Entity EJB作為商業數據層時,我們首先需要從資料庫載入數據,創建對應的Entity EJB實例,之後對內存中Entity EJB實例的屬性進行相應操作。對屬性的操作比較直接的做法是:直接調用Entity EJB的getXXX()/setXXX(),通常利用EJB2.0的本地介面;通過DTO Factory生成DTO。但這兩種做法都存在如下問題:
1. 當Entity EJB的屬性特別多時候,以上做法會帶來復雜羅嗦的代碼,使EJB變的龐大無比。
2. 使Entity EJB的客戶端(比如Session EJB)和Entity EJB的介面緊密關聯。Entity EJB屬性的增刪都需要更改客戶端代碼,給項目開發和維護帶來不便。
事實上可以利用更通用的方式訪問Entity EJB的屬性,即定義Generic Attribute Access Interface。見下圖8:
圖8:Generic Attribute Access Interface示例
Generic Attribute Access Interface由Entity EJB的本地或遠程介面實現,並利用Hash Maps傳輸數據。實現方式常見如下:
1. BMP類型實體EJB可以在Bean類中定義包含所有屬性的私有成員變數HashMap。
2. CMP類型實體EJB可以在Bean類中可以適用Java Reflection API實現。
3. 建立一個父類,在不同的情況下定義子類重載父類方法。
使用Generic Attribute Access Interface需要在客戶端與伺服器端對屬性以及對應的關鍵字建立統一的命名習慣。常見的做法如下:
1. 建立並保持良好的文檔記錄和命名約定。
2. 在實體EJB的實現類中定義靜態成員映射屬性。
3. 創建共享靜態類,通過成員變數映射實體EJB屬性。
4. 通過JNDI在伺服器端保存屬性映射關系。
Generic Attribute Access Interface的運用帶來一下益處:
1. 介面實現後對不通實體EJB都適用。
2. 對屬性較多實體EJB能精簡代碼,並更具維護性。
3. 使運行中動態增刪實體EJB屬性成為可能。
Generic Attribute Access Interface的缺點在於:
1. 訪問EJB屬性時增加了額外的操作。需要通過關鍵字映射屬性,最後還需進行類型轉換。
2. 需要建立客戶端與伺服器端的命名約定。
3. 因為通過HashMap操作時候需要進行類型轉換,容易產生運行時類型不匹配異常。
Business Interface
EJB規范要求Bean實現類必須實現所有在遠程(或本地)介面中定義的所有方法,同時不允許Bean實現類直接繼承遠程(或本地)介面。這就導致編譯時候很容易產生兩者不一致的問題,即遠程(或本地)介面中定義的某方法為在Bean實現類中被實現等錯誤。為避免上訴錯誤,可以利用應用伺服器廠商所提供的工具。但也可以應用EJB的設計架構來實現:定義商業介面。
Business Interface即創建自定義商業介面,在介面中定義所有EJB提供的商業方法,並讓Bean實現類和遠程(或本地)介面都實現該商業介面。其繼承關系見下圖9:
圖9:商業介面的使用
Business Interface是個普通的Java Class。依賴於使用本地介面與遠程介面的不通,Business Interface的定義略有不同:應用與遠程介面時,在介面中的方法需要拋出java.rmi.RemoteException;而應用與本地介面時候則不需要作任何特別處理。
應用Business Interface時候必須注意一點:EJB規范不允許直接EJB的實例將對自己的引用(this對象)返回給客戶端,否則編譯時候即報錯。但使用Business Interface後,編譯時候無法檢查出有無將this對象返回給客戶端。這一點需要程序員自己保證。
三. 內部數據轉換策略
Data Transfer Object
基於EJB的J2EE多層架構應用中,經常涉及的一個問題就是如何在各層之間傳遞批量數據,比如客戶端對伺服器端數據的批量讀寫操作等。比如需要得到實體EJB的屬性,直接的方法是多次調用不通的屬性,如下圖10:
圖10:低效的數據傳遞方式
但這種方法容易導致許多問題,比如性能以及代碼的復雜度等,更有效的辦法是在一個調用中得到所有需要的屬性。所以可以引入Data Transfer Object來封裝所需要的屬性,並在客戶與伺服器端通過傳遞該對象一次實現對數據的操作。如下圖11:
圖11:通過DTO傳遞數據
DTO為普通的Java Class,通常是伺服器端數據的快照。由於網路傳輸的需要,DTO應該實現java.io.Serializable介面。
DTO的設計有兩種模型:Domain DTO以及Custom DTO。
Domain DTO僅僅實現對伺服器數據的拷貝,通常與實體EJB為一對一的關系(也存在為多個相關聯的實體EJB對應一個Domain DTO)。Domain DTO通常除用於讀取更改實體EJB屬性外也可用於創建實體EJB時候。實體EJB與Domain DTO對應關系如下圖12:
圖12:Account EJB 與 Account DomainDTO
Domain DTO的應用除了DTO所具有的一般優點外,還有別的益處:
1. 開發迅速。因為一旦實體EJB設計好後,很容易轉換得到Domain DTO。
2. 可以利用Domain DTO的setXXX()方法在客戶端進行屬性有效性效驗。
Domain DTO的缺點有:
1. 客戶端綁定了伺服器端數據模型,不利於維護。
2. 不夠靈活,無法處理客戶端的多樣化數據要求。對一個數百個屬性的實體EJB請求一個屬性時候卻返回一個包含所有屬性值的Domain DTO明顯是笨重的實現。
3. 導致代碼的重復。
4. Domain DTO中如果嵌套包含了別的Domain DTO時,一旦需伺服器端數據的更改而需要重定義Domain DTO模型時候異常困難。
Custom DTO則可以克服上述的一些缺點。Customer DTO僅僅封裝用戶感興趣的伺服器數據集即可以根據客戶端需求創建Customer DTO。這樣作的優點是靈活高效;缺點是大項目中可能導致大量的Customer DTO存在。
通常Domain DTO可以用於數據的更新與創建;Customer DTO可以用於客戶用於表現層的數據讀取。兩者可以相輔相成。而且使用DTO一般與DTO Factory同時使用。
Domain Transfer Hash Map
DTO的使用往往缺乏通用性。不通的用戶案例需要創建不同的DTO。當項目很復雜時,從維護性考慮需要更好的數據傳輸的實現方式。
Domain Transfer Hash Map即利用HashMap作為客戶所需數據集的封裝。好處是:
1. 良好的維護性。
2. 較大的通用性。不同的客戶端可以使用相同的數據傳遞方式。
缺點是:
1. 需要維護客戶端與伺服器端在屬性及其對應關鍵字的映射關系。
2. 當需要使用基本類型的數據時候,因為Hash Map的限制必須將基本類型先轉換成對象。
3. 使用得到的數據時,需要進行類型強制轉換。
Data Transfer RowSet
當需要處理直接的JDBC調用得到的結果集時,顯然用DTO/Hash Map已經不合適,因為需要對大量數據進行類型轉換等額外操作是很費資源和不必要的,而且最終用戶常需要以表格式樣顯示數據。
所以對二維表式數據,更好的處理方式是利用Data Transfer RowSet。Data Transfer RowSet通過將ResultSet直接轉換為RowSet傳遞給客戶端。
在Session EJB中使用RowSet的一段示例代碼如下圖13:
圖13:使用RowSet
使用RowSet的好處很多:
1. 介面通用於各樣的資料庫查詢操作。
2. 當需要表格式數據顯示時,因為直接從ResultSet得到,所以不需要額外的數據類型轉換。
缺點是:
1. 資料庫結構暴露給客戶端。
2. 不符合面向對象設計思想。
3. 依賴於SQL。
Data Transfer RowSet通常用於只讀式數據的顯示操作,經常和JDBC for Reading Pattern連用。
四.事務和數據持久機制
JDBC for Reading Pattern
基於EJB的J2EE應用中,通過EJB對資料庫的操作可以有兩種方式:實體EJB或者Session EJB中直接利用JDBC訪問。
客戶很多時候取出資料庫中數據並以表格方式顯示。這種情形如果使用實體EJB會導致如下問題:
1. 引用伺服器端頻繁的資料庫查詢和載入操作。因為載入N個實體EJB總需要進行一次find()操作N次數據載入。
2. 如果使用Remote介面,引起頻繁的額外網路操作。
3. 對關聯關系比較復雜的資料庫表結構,很難直接通過Entity EJB表現。
因此建議在只需對資料庫表數據進行只讀訪問時候,應該採用JDBC for Reading Pattern,即通過JDBC直接訪問資料庫。除了避免上述使用實體EJB的缺點還帶來一下好處:
1. 充分利用資料庫能力,比如資料庫的緩存機制。
2. 減少了對事務控制的資源。
3. 利用自定義SQL可以按需要比較靈活的讀取數據。
4. 只需要一次數據查詢,減少了資料庫操作。
缺點是:
1. 於J2EE應用的面向對象設計相違背。
2. 因為Session EJB代碼中包含了自定義SQL,維護性差。
3. Session EJB中不得不包含JDBC的API,並且需要了解資料庫結構。
部屬人員: 使用相應工具在運行環境下配置 EJB
系統管理員: 監視運行時情況
G. java後端程序員最常用的技術有哪些,重點技術有哪些
Java學習路線,希望看完之後能給你帶來幫助。
第一步學習JavaEE基礎
Java是一種面向對象的編程語言,所以首先需要從基礎學起,只有前期打牢基礎,之後深入學習才能游刃有餘。那麼基礎學習首先從基礎語法、面向對象、核心類庫、集合、異常、IO、線程、網路編程、反射、JDK1.8新特性這幾個方面展開,學習基礎階段培養面向對象的編程思想、充分理解並運用Java面向對象思想來進行程序開發、從過程到面向對象編程的轉變、,深入理解常用集合類的用法、集合的特點、內存理解以及使用;掌握多線程的概念、創建方式、同步、網路編程的基本概念等。
第二步學習JavaWeb開發
JavaWeb開發是學習Java中必不可少的內容,雖然Java是偏向於後台開發的,但是前後端不可能完全分離,後端開發人員也需要掌握一定的前端技能。JavaWeb開發可以從前端技術、MySQL、JDBC&JDBCUtils、XML、伺服器&Servlet、JSP、AJAX幾點來學習,以此來掌握使用HTML、CSS進行前端界面的設計、掌握對JavaScript、JQuery基本語法的使用;掌握XML的解析方式、掌握伺服器的概念以及其配置、熟悉Servlet開發規范和相關概念、JSP基本原理、Session和Cookie、過濾器和監聽器的使用、以及Ajax非同步請求。
第三步Java高級框架
雖然說Java框架有很多,但是比較常用和主流的還是比較固定的,靈活的使用框架可以讓開發者在實際開發中,減少很多重復的代碼、讓代碼的結構更加清晰,後期維護方便。從現在的開發環境來看SpringMVC、Mybatis、Spring、Oracle、Linux&Redis&Nginx、Maven是現在普遍使用的主流框架,掌握之後可以實現從原理、應用、擴展等全方位角度熟練使用,最終可以搭建自己的平台。
第四步分布式項目實戰
學習的最終目的就是上手實操,根據項目需求開發功能,那麼實戰就顯得尤為重要了,所以最後一步是項目實戰,那Git、SpringBoot、SpringCloud 等主流技術必定是需要熟練掌握的,通過學習掌握分布式調用技術任務調度以及項目相關模塊之間的開發和關聯,從而達到實現功能開發目的。
初學Java你需要學習JDK,JDK是一個編寫Java的Applet小程序和應用程序的程序開發環境。JDK是整個Java的核心,包括了Java運行環境,一些Java工具和Java的核心類庫。不論什麼Java應用伺服器實質都是內置了某個版本的JDK。所以學好JDK是掌握Java的第一步。
學好JDK後,還有其他幾種軟體如果你感興趣也可以學一學,這幾種軟體分別為:Eclipse:一個開放源代碼的、基於Java的可擴展開發平台;EditPlus:文本編譯工具,初學者可以使用EditPlus編譯執行Java程序;NetBeans:開放源碼的Java集成開發環境,適用於各種客戶機和Web應用;IntelliJ IDEA:可以用於代碼自動提示、代碼分析等;MyEclipse:由Genuitec公司開發的一款商業化軟體,是應用比較廣泛的Java應用程序集成開發環境;SQL Server:資料庫軟體,做web開發會用到這個軟體。
綜上可以看出,學習Java需要的軟體不少,如果自學一個個了解過去的話比較費時間,而報班就不同了,報班學習會有老師帶著你一步步下載、安裝、學習各個軟體,這樣不但能節省很多時間,還能讓你把這些軟體掌握的更好。
Java學習上手比較難,需要的軟體也多種多樣
Java框架可以簡化開發難度,更便於我們開發程序。所以學好Java框架還是比較重要的。Java的框架主要有:SpringMVC、Spring、Mybatis、Dubbo、Maven、RabbitMQ、Log4j、Ehcache、Redis、Shiro。不過這十個我們不需要都學會,只要學會其中四五個比較常用的就可以。
第一個,SpringMVC。Spring MVC是一種基於Java的實現了Web MVC設計模式的請求驅動類型的輕量級Web框架,主要是幫助我們簡化日常的Web開發;第二個,Mybatis。MyBatis 是支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架;第三個,Spring。Spring深得企業的青睞;第四個,Maven。越來越多的開發人員開始使用maven。
掌握以上四種框架,你在找工作的時候就會比較吃香。不過想把這四種框架學會也不容易。不了解Java的人可能看的都一頭霧水更別說學習了。這是因為想要學習Java框架還要從Java的基礎部分學起。而從基礎部分自學到Java框架,花費的時間就長了。
所以小編建議大家報班學習Java,培訓班的學習時長為半年左右。相比於自學,耗時少了不少。而且培訓班不止能幫助你快速掌握理論知識,還有實戰項目助你鞏固所學。例如優就業的Java課程在Java框架部分,每個框架都對應一個小項目。這一階段學完後還會有一個大項目讓學員練手,增加學員的項目開發經驗。所以報班學習更容易學會Java。
H. java多線程開發的同步機制有哪些
Java同步
標簽: 分類:
一、關鍵字:
thread(線程)、thread-safe(線程安全)、intercurrent(並發的)
synchronized(同步的)、asynchronized(非同步的)、
volatile(易變的)、atomic(原子的)、share(共享)
二、總結背景:
一次讀寫共享文件編寫,嚯,好傢伙,竟然揪出這些零碎而又是一路的知識點。於是乎,Google和翻閱了《Java參考大全》、《Effective Java Second Edition》,特此總結一下供日後工作學習參考。
三、概念:
1、 什麼時候必須同步?什麼叫同步?如何同步?
要跨線程維護正確的可見性,只要在幾個線程之間共享非 final 變數,就必須使用 synchronized(或 volatile)以確保一個線程可以看見另一個線程做的更改。
為了在線程之間進行可靠的通信,也為了互斥訪問,同步是必須的。這歸因於java語言規范的內存模型,它規定了:一個線程所做的變化何時以及如何變成對其它線程可見。
因為多線程將非同步行為引進程序,所以在需要同步時,必須有一種方法強制進行。例如:如果2個線程想要通信並且要共享一個復雜的數據結構,如鏈表,此時需要
確保它們互不沖突,也就是必須阻止B線程在A線程讀數據的過程中向鏈表裡面寫數據(A獲得了鎖,B必須等A釋放了該鎖)。
為了達到這個目的,java在一個舊的的進程同步模型——監控器(Monitor)的基礎上實現了一個巧妙的方案:監控器是一個控制機制,可以認為是一個
很小的、只能容納一個線程的盒子,一旦一個線程進入監控器,其它的線程必須等待,直到那個線程退出監控為止。通過這種方式,一個監控器可以保證共享資源在
同一時刻只可被一個線程使用。這種方式稱之為同步。(一旦一個線程進入一個實例的任何同步方法,別的線程將不能進入該同一實例的其它同步方法,但是該實例
的非同步方法仍然能夠被調用)。
錯誤的理解:同步嘛,就是幾個線程可以同時進行訪問。
同步和多線程關系:沒多線程環境就不需要同步;有多線程環境也不一定需要同步。
鎖提供了兩種主要特性:互斥(mutual exclusion) 和可見性(visibility)。
互斥即一次只允許一個線程持有某個特定的鎖,因此可使用該特性實現對共享數據的協調訪問協議,這樣,一次就只有一個線程能夠使用該共享數據。
可見性要更加復雜一些,documents它必須確保釋放鎖之前對共享數據做出的更改對於隨後獲得該鎖的另一個線程是可見的 —— 如果沒有同步機制提供的這種可見性保證,線程看到的共享變數可能是修改前的值或不一致的值,這將引發許多嚴重問題
小結:為了防止多個線程並發對同一數據的修改,所以需要同步,否則會造成數據不一致(就是所謂的:線程安全。如java集合框架中Hashtable和
Vector是線程安全的。我們的大部分程序都不是線程安全的,因為沒有進行同步,而且我們沒有必要,因為大部分情況根本沒有多線程環境)。
2、 什麼叫原子的(原子操作)?
Java原子操作是指:不會被打斷地的操作。(就是做到互斥 和可見性?!)
那難道原子操作就可以真的達到線程安全同步效果了嗎?實際上有一些原子操作不一定是線程安全的。
那麼,原子操作在什麼情況下不是線程安全的呢?也許是這個原因導致的:java線程允許線程在自己的內存區保存變數的副本。允許線程使用本地的私有拷貝進
行工作而非每次都使用主存的值是為了提高性能(本人愚見:雖然原子操作是線程安全的,可各線程在得到變數(讀操作)後,就是各自玩
弄自己的副本了,更新操作(寫操作)因未寫入主存中,導致其它線程不可見)。
那該如何解決呢?因此需要通過java同步機制。
在java中,32位或者更少位數的賦值是原子的。在一個32位的硬體平台上,除了double和long型的其它原始類型通常都
是使用32位進行表示,而double和long通常使用64位表示。另外,對象引用使用本機指針實現,通常也是32位的。對這些32位的類型的操作是原
子的。
這些原始類型通常使用32位或者64位表示,這又引入了另一個小小的神話:原始類型的大小是由語言保證的。這是不對的。java語言保證的是原始類型的表
數范圍而非JVM中的存儲大小。因此,int型總是有相同的表數范圍。在一個JVM上可能使用32位實現,而在另一個JVM上可能是64位的。在此再次強
調:在所有平台上被保證的是表數范圍,32位以及更小的值的操作是原子的。
3、 不要搞混了:同步、非同步
舉個例子:普通B/S模式(同步)AJAX技術(非同步)
同步:提交請求->等待伺服器處理->處理完返回 這個期間客戶端瀏覽器不能幹任何事
非同步:請求通過事件觸發->伺服器處理(這是瀏覽器仍然可以作其他事情)->處理完畢
可見,彼「同步」非此「同步」——我們說的java中的那個共享數據同步(synchronized)
一個同步的對象是指行為(動作),一個是同步的對象是指物質(共享數據)。
4、 Java同步機制有4種實現方式:(部分引用網上資源)
① ThreadLocal ② synchronized( ) ③ wait() 與 notify() ④ volatile
目的:都是為了解決多線程中的對同一變數的訪問沖突
ThreadLocal
ThreadLocal 保證不同線程擁有不同實例,相同線程一定擁有相同的實例,即為每一個使用該變數的線程提供一個該變數值的副本,每一個線程都可以獨立改變自己的副本,而不是與其它線程的副本沖突。
優勢:提供了線程安全的共享對象
與其它同步機制的區別:同步機制是為了同步多個線程對相同資源的並發訪問,是為了多個線程之間進行通信;而 ThreadLocal 是隔離多個線程的數據共享,從根本上就不在多個線程之間共享資源,這樣當然不需要多個線程進行同步了。
volatile
volatile 修飾的成員變數在每次被線程訪問時,都強迫從共享內存中重讀該成員變數的值。而且,當成員變數發生變化時,強迫線程將變化值回寫到共享內存。
優勢:這樣在任何時刻,兩個不同的線程總是看到某個成員變數的同一個值。
緣由:Java
語言規范中指出,為了獲得最佳速度,允許線程保存共享成員變數的私有拷貝,而且只當線程進入或者離開同步代碼塊時才與共享成員變數的原
始值對比。這樣當多個線程同時與某個對象交互時,就必須要注意到要讓線程及時的得到共享成員變數的變化。而 volatile
關鍵字就是提示 VM :對於這個成員變數不能保存它的私有拷貝,而應直接與共享成員變數交互。
使用技巧:在兩個或者更多的線程訪問的成員變數上使用 volatile 。當要訪問的變數已在 synchronized 代碼塊中,或者為常量時,不必使用。
線程為了提高效率,將某成員變數(如A)拷貝了一份(如B),線程中對A的訪問其實訪問的是B。只在某些動作時才進行A和B的同步,因此存在A和B不一致
的情況。volatile就是用來避免這種情況的。
volatile告訴jvm,它所修飾的變數不保留拷貝,直接訪問主內存中的(讀操作多時使用較好;線程間需要通信,本條做不到)
Volatile 變數具有 synchronized 的可見性特性,但是不具備原子特性。這就是說線程能夠自動發現 volatile
變數的最新值。Volatile
變數可用於提供線程安全,但是只能應用於非常有限的一組用例:多個變數之間或者某個變數的當前值與修改後值
之間沒有約束。
您只能在有限的一些情形下使用 volatile 變數替代鎖。要使 volatile 變數提供理想的線程安全,必須同時滿足下面兩個條件:
對變數的寫操作不依賴於當前值;該變數沒有包含在具有其他變數的不變式中。
sleep() vs wait()
sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,把執行機會給其他線程,但是監控狀態依然保持,到時後會自動恢復。調用sleep不會釋放對象鎖。
wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)後本線程才進入對象鎖定池准備獲得對象鎖進入運行狀態。
(如果變數被聲明為volatile,在每次訪問時都會和主存一致;如果變數在同步方法或者同步塊中被訪問,當在方法或者塊的入口處獲得鎖以及方法或者塊退出時釋放鎖時變數被同步。)
I. java常見面試題
1、面向對象的特徵有哪些方面
(1)抽象:
抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。抽象並不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽象,二是數據抽象。
(2)繼承:
繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。對象的一個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的基類那裡繼承方法和實例變數,並且類可以修改或增加新的方法使之更適合特殊的需要。
(3)封裝:
封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。面向對象計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的介面訪問其他對象。
(4) 多態性:
多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。多態性語言具有靈活、抽象、行為共享、代碼共享的優勢,很好的解決了應用程序函數同名問題。
2、String是最基本的數據類型嗎?
基本數據類型包括byte、int、char、long、float、double、boolean和short。
java.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。為了提高效率節省空間,我們應該用StringBuffer類
3、int 和 Integer 有什麼區別
Java 提供兩種不同的類型:引用類型和原始類型(或內置類型)。Int是java的原始數據類型,Integer是java為int提供的封裝類。Java為每個原始類型提供了封裝類。
原始類型封裝類
booleanBoolean
charCharacter
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
引用類型和原始類型的行為完全不同,並且它們具有不同的語義。引用類型和原始類型具有不同的特徵和用法,它們包括:大小和速度問題,這種類型以哪種類型的數據結構存儲,當引用類型和原始類型用作某個類的實例數據時所指定的預設值。對象引用實例變數的預設值為 null,而原始類型實例變數的預設值與它們的類型有關。
4、String 和StringBuffer的區別
JAVA 平台提供了兩個類:String和StringBuffer,它們可以儲存和操作字元串,即包含多個字元的字元數據。這個String類提供了數值不可改變的字元串。而這個StringBuffer類提供的字元串進行修改。當你知道字元數據要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態構造字元數據。
5、運行時異常與一般異常有何異同?
異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤。java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是並不要求必須聲明拋出未被捕獲的運行時異常。
6、說出Servlet的生命周期,並說出Servlet和CGI的區別。
Servlet被伺服器實例化後,容器運行其init方法,請求到達時運行其service方法,service方法自動派遣運行與請求對應的doXXX方法(doGet,doPost)等,當伺服器決定將實例銷毀的時候調用其destroy方法。
與cgi的區別在於servlet處於伺服器進程中,它通過多線程方式運行其service方法,一個實例可以服務於多個請求,並且其實例一般不會銷毀,而CGI對每個請求都產生新的進程,服務完成後就銷毀,所以效率上低於servlet。
7、說出ArrayList,Vector, LinkedList的存儲性能和特性
ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector由於使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行前向或後向遍歷,但是插入數據時只需要記錄本項的前後項即可,所以插入速度較快。
8、EJB是基於哪些技術實現的?並說出SessionBean和EntityBean的區別,StatefulBean和StatelessBean的區別。
EJB包括Session Bean、Entity Bean、Message Driven Bean,基於JNDI、RMI、JAT等技術實現。
SessionBean在J2EE應用程序中被用來完成一些伺服器端的業務操作,例如訪問資料庫、調用其他EJB組件。EntityBean被用來代表應用系統中用到的數據。
對於客戶機,SessionBean是一種非持久性對象,它實現某些在伺服器上運行的業務邏輯。
對於客戶機,EntityBean是一種持久性對象,它代表一個存儲在持久性存儲器中的實體的對象視圖,或是一個由現有企業應用程序實現的實體。
Session Bean 還可以再細分為 Stateful Session Bean 與 Stateless Session Bean ,這兩種的 Session Bean都可以將系統邏輯放在 method之中執行,不同的是 Stateful Session Bean 可以記錄呼叫者的狀態,因此通常來說,一個使用者會有一個相對應的 Stateful Session Bean 的實體。Stateless Session Bean 雖然也是邏輯組件,但是他卻不負責記錄使用者狀態,也就是說當使用者呼叫 Stateless Session Bean 的時候,EJB Container 並不會找尋特定的 Stateless Session Bean 的實體來執行這個 method。換言之,很可能數個使用者在執行某個 Stateless Session Bean 的 methods 時,會是同一個 Bean 的 Instance 在執行。從內存方面來看, Stateful Session Bean 與 Stateless Session Bean 比較, Stateful Session Bean 會消耗 J2EE Server 較多的內存,然而 Stateful Session Bean 的優勢卻在於他可以維持使用者的狀態。
9、Collection 和 Collections的區別。
Collection是集合類的上級介面,繼承與他的介面主要有Set 和List.
Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。
10、&和&&的區別。
&是位運算符,表示按位與運算,&&是邏輯運算符,表示邏輯與(and)。
11、HashMap和Hashtable的區別。
HashMap是Hashtable的輕量級實現(非線程安全的實現),他們都完成了Map介面,主要區別在於HashMap允許空(null)鍵值(key),由於非線程安全,效率上可能高於Hashtable。
HashMap允許將null作為一個entry的key或者value,而Hashtable不允許。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap 就必須為之提供外同步。
Hashtable和HashMap採用的hash/rehash演算法都大概一樣,所以性能不會有很大的差異。
12、final, finally, finalize的區別。
final 用於聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
finally是異常處理語句結構的一部分,表示總是執行。
finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等。
13、sleep() 和 wait() 有什麼區別?
sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,把執行機會給其他線程,但是監控狀態依然保持,到時後會自動恢復。調用sleep不會釋放對象鎖。
wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)後本線程才進入對象鎖定池准備獲得對象鎖進入運行狀態。
14、Overload和Override的區別。Overloaded的方法是否可以改變返回值的類型?
方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被"屏蔽"了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。
15、error和exception有什麼區別?
error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。
exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。
16、同步和非同步有何異同,在什麼情況下分別使用他們?舉例說明。
如果數據將在線程間共享。例如正在寫的數據以後可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那麼這些數據就是共享數據,必須進行同步存取。
當應用程序在對象上調用了一個需要花費很長時間來執行的方法,並且不希望讓程序等待方法的返回時,就應該使用非同步編程,在很多情況下採用非同步途徑往往更有效率。
17、abstract class和interface有什麼區別?
聲明方法的存在而不去實現它的類被叫做抽象類(abstract class),它用於要創建一個體現某些基本行為的類,並為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract 類的實例。然而可以創建一個變數,其類型是一個抽象類,並讓它指向具體子類的一個實例。不能有抽象構造函數或抽象靜態方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現,否則它們也是抽象類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。
介面(interface)是抽象類的變體。在介面中,所有方法都是抽象的。多繼承性可通過實現這樣的介面而獲得。介面中的所有方法都是抽象的,沒有一個有程序體。介面只可以定義static final成員變數。介面的實現與子類相似,除了該實現類不能從介面定義中繼承行為。當類實現特殊介面時,它定義(即將程序體給予)所有這種介面的方法。然後,它可以在實現了該介面的類的任何對象上調用介面的方法。由於有抽象類,它允許使用介面名作為引用變數的類型。通常的動態聯編將生效。引用可以轉換到介面類型或從介面類型轉換,instanceof 運算符可以用來決定某對象的類是否實現了介面。
18、heap和stack有什麼區別。
棧是一種線形集合,其添加和刪除元素的操作應在同一段完成。棧按照後進先出的方式進行處理。
堆是棧的一個組成元素
19、forward 和redirect的區別
forward是伺服器請求資源,伺服器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然後把這些內容再發給瀏覽器,瀏覽器根本不知道伺服器發送的內容是從哪兒來的,所以它的地址欄中還是原來的地址。
redirect就是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址,一般來說瀏覽器會用剛才請求的所有參數重新請求,所以session,request參數都可以獲取。
20、EJB與JAVA BEAN的區別?
Java Bean 是可復用的組件,對Java Bean並沒有嚴格的規范,理論上講,任何一個Java類都可以是一個Bean。但通常情況下,由於Java Bean是被容器所創建(如Tomcat)的,所以Java Bean應具有一個無參的構造器,另外,通常Java Bean還要實現Serializable介面用於實現Bean的持久性。Java Bean實際上相當於微軟COM模型中的本地進程內COM組件,它是不能被跨進程訪問的。Enterprise Java Bean 相當於DCOM,即分布式組件。它是基於Java的遠程方法調用(RMI)技術的,所以EJB可以被遠程訪問(跨進程、跨計算機)。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理, EJB組件由容器所創建和管理。客戶通過容器來訪問真正的EJB組件。
21、Static Nested Class 和 Inner Class的不同。
Static Nested Class是被聲明為靜態(static)的內部類,它可以不依賴於外部類實例被實例化。而通常的內部類需要在外部類實例化後才能實例化。
22、JSP中動態INCLUDE與靜態INCLUDE的區別?
動態INCLUDE用jsp:include動作實現 <!--include file="included.htm"-->
23、什麼時候用assert。
assertion (斷言)在軟體開發中是一種常用的調試方式,很多開發語言中都支持這種機制。在實現中,assertion就是在程序中的一條語句,它對一個 boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值為true;如果該值為false,說明程序已經處於不正確的狀態下,系統將給出警告或退出。一般來說,assertion用於保證程序最基本、關鍵的正確性。assertion檢查通常在開發和測試時開啟。為了提高性能,在軟體發布後,assertion檢查通常是關閉的。
24、GC是什麼? 為什麼要有GC?
GC是垃圾收集的意思(Gabage Collection),內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。
25、short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?
short s1 = 1; s1 = s1 + 1; (s1+1運算結果是int型,需要強制轉換類型)
short s1 = 1; s1 += 1;(可以正確編譯)
26、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round(11.5)==12
Math.round(-11.5)==-11
round方法返回與參數最接近的長整數,參數加1/2後求其floor.
27、String s = new String("xyz");創建了幾個String Object?
兩個(一個是「xyx」,一個是指向「xyx」的引用對象s)
J. java多線程編程實戰指南 怎麼樣
Active Object模式簡介
Active Object模式是一種非同步編程模式。它通過對方法的調用與方法的執行進行解耦來提高並發性。若以任務的概念來說,Active Object模式的核心則是它允許任務的提交(相當於對非同步方法的調用)和任務的執行(相當於非同步方法的真正執行)分離。這有點類似於 System.gc()這個方法:客戶端代碼調用完gc()後,一個進行垃圾回收的任務被提交,但此時JVM並不一定進行了垃圾回收,而可能是在gc() 方法調用返回後的某段時間才開始執行任務——回收垃圾。我們知道,System.gc()的調用方代碼是運行在自己的線程上(通常是main線程派生的子 線程),而JVM的垃圾回收這個動作則由專門的線程(垃圾回收線程)來執行的。換言之,System.gc()這個方法所代表的動作(其所定義的功能)的 調用方和執行方是運行在不同的線程中的,從而提高了並發性。
再進一步介紹Active Object模式,我們可先簡單地將其核心理解為一個名為ActiveObject的類,該類對外暴露了一些非同步方法,如圖1所示。
圖 1. ActiveObject對象示例
doSomething方法的調用方和執行方運行在各自的線程上。在並發的環境下,doSomething方法會被多個線程調用。這時所需的線程安 全控制封裝在doSomething方法背後,使得調用方代碼無需關心這點,從而簡化了調用方代碼:從調用方代碼來看,調用一個Active Object對象的方法與調用普通Java對象的方法並無太大差別。如清單1所示。
清單 1. Active Object方法調用示例
ActiveObject ao=...;
Future future = ao.doSomething("data");
//執行其它操作
String result = future.get();
System.out.println(result);
Active Object模式的架構
當Active Object模式對外暴露的非同步方法被調用時,與該方法調用相關的上下文信息,包括被調用的非同步方法名(或其代表的操作)、調用方代碼所傳遞的參數等,會 被封裝成一個對象。該對象被稱為方法請求(Method Request)。方法請求對象會被存入Active Object模式所維護的緩沖區(Activation Queue)中,並由專門的工作線程負責根據其包含的上下文信息執行相應的操作。也就是說,方法請求對象是由運行調用方代碼的線程通過調用Active Object模式對外暴露的非同步方法生成的,而方法請求所代表的操作則由專門的線程來執行,從而實現了方法的調用與執行的分離,產生了並發。
Active Object模式的主要參與者有以下幾種。其類圖如圖2所示。
圖 2. Active Object模式的類圖
(點擊圖像放大)
Proxy:負責對外暴露非同步方法介面。當調用方代碼調用該參與者實例的非同步方法doSomething時,該方法會生成一個相 應的MethodRequest實例並將其存儲到Scheler所維護的緩沖區中。doSomething方法的返回值是一個表示其執行結果的外包裝 對象:Future參與者的實例。非同步方法doSomething運行在調用方代碼所在的線程中。
MethodRequest:負責將調用方代碼對Proxy實例的非同步方法的調用封裝為一個對象。該對象保留了非同步方法的名稱及調用方代碼傳遞的參數等上下文信息。它使得將Proxy的非同步方法的調用和執行分離成為可能。其call方法會根據其所包含上下文信息調用Servant實例的相應方法。
ActivationQueue:負責臨時存儲由Proxy的非同步方法被調用時所創建的MethodRequest實例的緩沖區。
Scheler:負責將Proxy的非同步方法所創建的MethodRequest實例存入其維護的緩沖區中。並根據一定的調 度策略,對其維護的緩沖區中的MethodRequest實例進行執行。其調度策略可以根據實際需要來定,如FIFO、LIFO和根據 MethodRequest中包含的信息所定的優先順序等。
Servant:負責對Proxy所暴露的非同步方法的具體實現。
Future:負責存儲和返回Active Object非同步方法的執行結果。
Active Object模式的序列圖如圖3所示。
圖 3. Active Object模式的序列圖
(點擊圖像放大)
第1步:調用方代碼調用Proxy的非同步方法doSomething。
第2~7步:doSomething方法創建Future實例作為該方法的返回值。並將調用方代碼對該方法的調用封裝為MethodRequest 對象。然後以所創建的MethodRequest對象作為參數調用Scheler的enqueue方法,以將MethodRequest對象存入緩沖 區。Scheler的enqueue方法會調用Scheler所維護的ActivationQueue實例的enqueue方法,將 MethodRequest對象存入緩沖區。
第8步:doSomething返回其所創建的Future實例。
第9步:Scheler實例採用專門的工作線程運行dispatch方法。
第10~12步:dispatch方法調用ActivationQueue實例的dequeue方法,獲取一個MethodRequest對象。然後調用MethodRequest對象的call方法
第13~16步:MethodRequest對象的call方法調用與其關聯的Servant實例的相應方法doSomething。並將Servant.doSomething方法的返回值設置到Future實例上。
第17步:MethodRequest對象的call方法返回。
上述步驟中,第1~8步是運行在Active Object的調用者線程中的,這幾個步驟實現了將調用方代碼對Active Object所提供的非同步方法的調用封裝成對象(Method Request),並將其存入緩沖區。這幾個步驟實現了任務的提交。第9~17步是運行在Active Object的工作線程中,這些步驟實現從緩沖區中讀取Method Request,並對其進行執行,實現了任務的執行。從而實現了Active Object對外暴露的非同步方法的調用與執行的分離。
如果調用方代碼關心Active Object的非同步方法的返回值,則可以在其需要時,調用Future實例的get方法來獲得非同步方法的真正執行結果。
Active Object模式實戰案例
某電信軟體有一個彩信短號模塊。其主要功能是實現手機用戶給其它手機用戶發送彩信時,接收方號碼可以填寫為對方的短號。例如,用戶13612345678給其同事13787654321發送彩信時,可以將接收方號碼填寫為對方的短號,如776,而非其真實的號碼。
該模塊處理其接收到的下發彩信請求的一個關鍵操作是查詢資料庫以獲得接收方短號對應的真實號碼(長號)。該操作可能因為資料庫故障而失敗,從而使整 個請求無法繼續被處理。而資料庫故障是可恢復的故障,因此在短號轉換為長號的過程中如果出現資料庫異常,可以先將整個下發彩信請求消息緩存到磁碟中,等到 資料庫恢復後,再從磁碟中讀取請求消息,進行重試。為方便起見,我們可以通過Java的對象序列化API,將表示下發彩信的對象序列化到磁碟文件中從而實 現請求緩存。下面我們討論這個請求緩存操作還需要考慮的其它因素,以及Active Object模式如何幫助我們滿足這些考慮。
首先,請求消息緩存到磁碟中涉及文件I/O這種慢的操作,我們不希望它在請求處理的主線程(即Web伺服器的工作線程)中執行。因為這樣會使該模塊 的響應延時增大,降低系統的響應性。並使得Web伺服器的工作線程因等待文件I/O而降低了系統的吞吐量。這時,非同步處理就派上用場了。Active Object模式可以幫助我們實現請求緩存這個任務的提交和執行分離:任務的提交是在Web伺服器的工作線程中完成,而任務的執行(包括序列化對象到磁碟 文件中等操作)則是在Active Object工作線程中執行。這樣,請求處理的主線程在偵測到短號轉長號失敗時即可以觸發對當前彩信下發請求進行緩存,接著繼續其請求處理,如給客戶端響 應。而此時,當前請求消息可能正在被Active Object線程緩存到文件中。如圖4所示。
圖 4 .非同步實現緩存
其次,每個短號轉長號失敗的彩信下發請求消息會被緩存為一個磁碟文件。但我們不希望這些緩存文件被存在同一個子目錄下。而是希望多個緩存文件會被存 儲到多個子目錄中。每個子目錄最多可以存儲指定個數(如2000個)的緩存文件。若當前子目錄已存滿,則新建一個子目錄存放新的緩存文件,直到該子目錄也 存滿,依此類推。當這些子目錄的個數到達指定數量(如100個)時,最老的子目錄(連同其下的緩存文件,如果有的話)會被刪除。從而保證子目錄的個數也是 固定的。顯然,在並發環境下,實現這種控制需要一些並發訪問控制(如通過鎖來控制),但是我們不希望這種控制暴露給處理請求的其它代碼。而Active Object模式中的Proxy參與者可以幫助我們封裝並發訪問控制。
下面,我們看該案例的相關代碼通過應用Active Object模式在實現緩存功能時滿足上述兩個目標。首先看請求處理的入口類。該類就是本案例的Active Object模式的客調用方代碼。如清單2所示。
清單 2. 彩信下發請求處理的入口類
public class MMSDeliveryServlet extends HttpServlet {
private static final long serialVersionUID = 5886933373599895099L;
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//將請求中的數據解析為內部對象
MMSDeliverRequest mmsDeliverReq = this.parseRequest(req.getInputStream());
Recipient shortNumberRecipient = mmsDeliverReq.getRecipient();
Recipient originalNumberRecipient = null;
try {
// 將接收方短號轉換為長號
originalNumberRecipient = convertShortNumber(shortNumberRecipient);
} catch (SQLException e) {
// 接收方短號轉換為長號時發生資料庫異常,觸發請求消息的緩存
AsyncRequestPersistence.getInstance().store(mmsDeliverReq);
// 繼續對當前請求的其它處理,如給客戶端響應
resp.setStatus(202);
}
}
private MMSDeliverRequest parseRequest(InputStream reqInputStream) {
MMSDeliverRequest mmsDeliverReq = new MMSDeliverRequest();
//省略其它代碼
return mmsDeliverReq;
}
private Recipient convertShortNumber(Recipient shortNumberRecipient)
throws SQLException {
Recipient recipent = null;
//省略其它代碼
return recipent;
}
}