路線圖
|
——併發,性能,字節碼,類加載java
——Java將來發展:lambda表達式,模塊化Jigsaw項目。程序員
初識Java7
|
Java7的變化爲兩塊:Coin項目,NIO.2。正則表達式
1.1 Java語言和平臺的區別編程
Java系統規範中最重要的是:《Java語言規範》JLR和《JVM規範》VMSpec。數組
鏈接Java語言平臺之間的是:統一的類文件.class格式定義。安全
大多數流行框架會在類加載過程當中對類進行改造。服務器
流程:.java(javac).class(類加載器)轉換後的.class(解釋器)可執行代碼(JIT編譯器)機器碼。網絡
注意:JVM字節碼實際上只是一種中間語言,不是真正的機器碼。多線程
而所謂的編譯器javac也不一樣於gcc,它只是一個針對Java源碼生成類文件的工具。併發
Java體系中真正的編譯器是JIT。
1.2 Coin項目:濃縮的都是精華
硬幣同樣小的變化。
提供新功能(難度遞增):1.類庫 2.工具提供的功能 3.語法糖4.語言新特性 5.類文件格式的變化 6.VM的新特性
——語法糖:數字中的下劃線(Java7)
——新的語言小特性,try-with-resources(Java7)
——類文件格式的變化,註解(Java5)
——JVM的新特性,動態調用(Java7)
Coin項目:3.語法糖4.語言新特性。
1.3 Coin項目中的修改
語法的6個新特性:
1.switch語句中的String。
2.數字常量的新形式。
3.改進的異常處理Multi-catch。
4.try-with-resources結構,自動關閉資源。
5.磚石語法:處理泛型。
6.變參警告位置的修改
1.3.1 switch語句中的String
支持byte,char,short,int,枚舉常量和String
1.3.2 更強的數值文本表示法
—— 數字常量可用二進制文本表示
—— 整形常量中可以使用下劃線
之前:int x = Integer.parseInt("1100110",2);
Java7:int x = 0b1100110 (與二進制打交道)
100_00_000:編譯器會在編譯時去掉下劃線
long anotherLong = 2_147_483-648L;
1.3.3 改善後的異常處理
multicatch與final重拋。
try{....} catch(FileNotFoundException | ParseExceptoin e) {.....}
catch(final Exception e ) {......}
final重拋:代表實際拋出的異常就是運行時遇到的異常。避免拋出籠統的異常類型。
1.3.4 try-with-resourch(TWR)
離開代碼塊時,資源自動關閉。文件或相似的東西。
把資源放在try的圓括號裏:
try( OutputStream out = new FileOutputStream(file);
InputStream is = url.openStream() ) {
byte[] buf = new byte[4096];
int len;
while((len = is.read(buf))>0){
out.write(buf,0,len);
}
}
資源自動化管理代碼塊的基本形式
正確的用法:爲各個資源聲明獨立變量
try(FileInputStream in = new FileInputStream("SomeFile.bin");
ObjectInputStream in = new ObjectInputStream(fin) ){......}
Java7中大多數資源類都被修改過,實現AutoCloseable接口。
1.3.5 磚石語法
針對建立泛型定義和實例太多繁瑣的問題
原來:
Map<Integer,Map<String,String>> usersLists =
new HashMap<Integer,Map<String,String>>();
類型推斷改進:
Map<Integer,Map<String,String>> usersLists =
new HashMap<>();
1.3.6 簡化變參方法調用
遠離類型系統
修改語言很是困難,用類庫實現新特性老是相對容易一些。
第2章 新I/O
本章內容:
——新I/O API(NIO.2)
——Path:基於文件和目錄的I/O新基礎
——Files應用類和各類輔助方法
——如何實現常見的I/O應用場景
——介紹異步I/O
核心類庫的變化,java.nio包內。掌握Java以前版本處理I/O的方法。
優勢:
——徹底取代java.io.File與文件系統的交互。
——新的異步處理類,無需手動配置線程池和其餘底層併發控制。即可在後臺線程中執行文件和網絡I/O操做。
——引入新的Network-Channel構造方法,簡化了套接字與通道的編碼工做。
Java7的NIO.2 API支持目錄樹導航(Files.walkFileTree()),符號連接Files.isSysbolicLink(),能用一行代碼讀取文件屬性(Files.readFileAttributes())
讀取這些文件極可能打斷程序的主流程。面對這一要求,在Java5/6時代可能會用java.util.concurrent中的類建立線程池和工做線程隊列,再用單獨後臺線程讀取文件。
NIO.2 API 中用AsynchronousFileChannel,不用指定工做線程或隊列就可在後臺讀取大型文件。
NIO2爲多線程文件和套接字訪問的應用提供了一個簡單的抽象層。IDE,應用服務器和各類流行的框架會大量應用這些特性。
將try-with-resources和NIO.2中的新API結合起來能夠寫出很是安全的I/O程序。
先了解新的文件系統抽象層:Path和它的輔助類。Path之上,經常使用的文件系統操做,複製和移動文件。
2.1 Java I/O簡史
|
2.1.1 Java1.0-1.3
缺少對非阻塞I/O的支持。
2.1.2 在Java1.4中引入NIO
——在Java1.4中引入非阻塞I/O
——在Java7中對非阻塞I/O進行修改
2002年發佈Java1.4時新增的特性:
——爲I/O操做抽象出緩衝區和通道層。
——字符集的編碼和解碼功能。
——提供了可以將文件映射爲內存數據的接口。
——實現非阻塞I/O的能力。
——基於流行的Perl實現的正則表達式類庫。
但那時對文件系統中的文件和目錄處理而言支持力度還不夠。那時的java.io.File類有些比較煩人的侷限性。
——在不一樣的平臺中對文件名的處理不一致。
——沒有統一的文件屬性模型(好比讀寫訪問模型)
——遍歷目錄困難。
——不能使用平臺/操做系統的特性
——不支持文件系統的非阻塞操做。
2.1.3 下一代I/O - NIO.2
NIO.2的三個主要目標:
(1)提供一個批量獲取文件屬性的文件系統接口。去掉和特定文件系統相關的API,還有一個用於引入標準文件系統實現的服務提供者接口。
(2)提供一個套接字和文件都可以進行異步(與輪詢、非阻塞相對)I/O操做的API。
(3)完成JSR-51中定義的套接字——通道功能,包括額外對綁定,選項配置和多播數據報的支持。
2.2 文件I/O的基石:Path
|
2.2.1 建立一個Path
Paths.get(String first, String...more)
Path listing = Path.get("/usr/bin/zip")
listing.toAbsolutePath()
2.2.2 從Path中獲取信息
正在處理的路徑的相關信息。
listing.getFileName()
listing.getNameCount()獲取名稱元素的數量
listing.getParent()
listing.getRoot()
listing.sunpath(0,2)
2.2.3 移除冗餘項
Path normalizedPath = Paths.get("./Listing_2_1.java").normalize();
toRealPath()方法融合了toAbsolutePath()和normalize()兩個方法,還能檢測並跟隨符號連接。
2.2.5 NIO.2 Path和Java已有的File類
File file = new File("../Listing_2_1.java");
Path listing = file.toPath();
listing.toAbsolutePath();
file = listing.toFile();
2.3 處理目錄和目錄樹
|
過濾流中使用到的模式匹配稱爲glob模式匹配。
2.3.2 遍歷目錄樹
Files.walkFileTree(Path startingDir, FileVisitor<? super Path> visitor);
默認實現類:SimpleFileVisitor<T>
public class Find
{
public static void main(String[] args) throws IOException
{
Path startingDir = Paths.get("C:\\workspace\\java7developer\\src");
Files.walkFileTree(startingDir,new FindJavaVisitor());
}
private static class FindJavaVisitor extends SimpleFileVisitor<Path>
{
@Override
public FindVisitorResult visitFile(Path file,BasicFileAttributes attrs)
{
if(file.toString().endsWith(".java")){
System.out.println(file.getFileName());
}
return FindVisitorResult.CONTINUE;
}
}
}
|
2.4 NIO.2的文件系統I/O
|
Path source = Path.get("...");
Files.copy(source,target,REPLACE_EXISTING);
Files.move(Path source,Path target,CopyOptions...);
2.4.3 文件的屬性
Files.getLastModifiedTime(zip);
Files.size(zip);
Files.readAttributes(zip,"*");
2.4.4 快速讀取文件
1.打開文件
用帶緩衝區的讀取器和寫入器或者輸入輸出流。
Path logFile = Paths.get("/tmp/app.log");
try(BufferedReader reader = Files.newBufferedReader(logFile,StandardCharsets.UTF_8)){
String line;
while( (line = reader.readline())!= null ){
...
}
}
打開寫入文件
Path logFile = Paths.get("/tmp/app.log");
try(BufferedWriter writer= Files.newBufferedWriter(logFile,StandardCharsets.UTF_8,StandardOpenOption.WRITE)){
Writer.write("hello world!");
...
}
}
設置字符編碼 new String(byte[],StandardCharsets.UTF_8)
兼容過去基於java.io包的I/O:
Files.newInputStream(Path,OpenOption...)
讀取所有行和所有字節的簡化方法:
Path logFile = Paths.get("/tmp/app.log");
List<String> lines = Files.readAllLines(logFile,StandardCharsets.UTF_8);
byte[] bytes = Files.readAllBytes(logFile);
2.4.5 文件修改通知
2.4.6 SeekableByteChannel
java.nio.channels.FileChannel
這個類的尋址能力讓開發人員能夠靈活的處理文件內容。
Path logFile = Paths.get("c:\\temp.log");
ByteBuffer buffer = ByteBuffer.allocate(1024);
FileChannel channel = FileChannel.open(logFile,StandardOpenOption.READ);
channel.read(buffer,channel.size() - 1000);
2.5 異步I/O 操做
|
做用:可使用多個後臺線程讀寫文件、套接字和通道中的數據。
AsynchronousFileChannel
AsynchronousSocketChannel
AsynchronousServerSocketChannel
使用java.util.concurrent.Future接口。
當你但願由主控線程發起I/O操做,並輪詢等待結果時,通常都會採用未來式異步處理。
Future:用來保存異步處理的操做結果。
實現:API/JVM爲執行這個任務建立了線程池和通道組。
AsynchronousFileChannel會關聯線程池,它的任務是接收I/O處理事件,並分發給負責處理通道中I/O操做結果的結果處理器。跟通道中發起的I/O操做關聯的結果處理器確保是由線程池中的某個線程產生的。
默認線程池是由AsynchronousChannelGroup類定義的系統屬性進行配置的。
2.5.2 回調式
主線程會派一個偵察員CompletionHandler到獨立的線程中執行I/O操做。這個偵查員將帶着I/O操做的結果返回到主線程中,這個結果會觸發本身的completed或failed方法。
在異步事件剛一成功或者失敗並須要立刻採起行動的時候,採用回調式。
代碼清單2-9 異步I/O——回調式
============================================
try
{
Path file = Paths.get("/usr/karianna/foobar.txt");
AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);
ByteBuffer buffer = ByteBuffer.allocate(100_000);
channel.read(buffer,0,buffer,new CompletionHandler<Integer,ByteBuffer>()
{
public void completed(Integer result,ByteBuffer attachment)
{
System.out.println("Bytes read [" + result + "]");
}
public void failed(Throwable exception,ByteBuffer attachment)
{
System.out.println(exception.getMessage());
}
});
}catch(IOException e)
{
System.out.println(e.getMessage());
}
|
2.6 Socket和Channel的整合
|
package com.java7developer.chapter2;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketOption;
import java.net.StandardSocketOptions;
import java.nio.channels.NetworkChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Set;
public class Listing_2_10 {
public static void main(String[] args) {
SelectorProvider provider = SelectorProvider.provider();
try {
NetworkChannel socketChannel = provider.openSocketChannel();
SocketAddress address = new InetSocketAddress(3080);
socketChannel = socketChannel.bind(address);
Set<SocketOption<?>> socketOptions = socketChannel.supportedOptions();
System.out.println(socketOptions.toString());
socketChannel.setOption(StandardSocketOptions.IP_TOS, 3);
Boolean keepAlive = socketChannel
.getOption(StandardSocketOptions.SO_KEEPALIVE);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
|
2.6.2 MuticastChannel
package com.java7developer.chapter2;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.StandardProtocolFamily;
import java.net.StandardSocketOptions;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;
public class Listing_2_11 {
public static void main(String[] args) {
try {//選擇網絡接口
NetworkInterface networkInterface = NetworkInterface.getByName("net1");
DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET);
dc.setOption(StandardSocketOptions.SO_REUSEADDR, true);
dc.bind(new InetSocketAddress(8080));
dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
InetAddress group = InetAddress.getByName("180.90.4.12");
MembershipKey key = dc.join(group, networkInterface);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
|
第二部分 關鍵技術
|
第3章 依賴注入
3.1 理解IoC和DI
|
package com.java7developer.chapter3;
import java.util.ArrayList;
import java.util.List;
/**
* Code for listing 3_4
*/
public class HollywoodServiceWithDI {
public static List<Agent> getFriendlyAgents(AgentFinder finder) {
List<Agent> agents = finder.findAllAgents();
List<Agent> friendlyAgents = filterAgents(agents, "Java Developers");
return friendlyAgents;
}
public static List<Agent> filterAgents(List<Agent> agents, String agentType) {
List<Agent> filteredAgents = new ArrayList<>();
for (Agent agent : agents) {
if (agent.getType().equals("Java Developers")) {
filteredAgents.add(agent);
}
}
return filteredAgents;
}
}
|
3.2 Java中標準的DI
|
3.3 Java中的DI參考實現:Guice 3
|
4.1 併發理論簡介
|
4.2 塊結構併發(Java5以前)
|
4.3 現代併發應用程序的構件
|
2006 Java5關鍵技術
1.依賴注入:解耦,可測試性,易讀性
2.併發編程:多核CPU革命
java.util.concurrent內存模型,線程與併發實現
3.類加載
JVM如何加載,連接和驗證類。用Javap深刻字節碼。
4.反射:Reflection
Java7的MethodHandle,MethodType和動態調用。
5.性能調優藝術
如何評測
6.垃圾回收GC和即時JIT編譯器
JVM中能影響性能的兩個主要部分
Java和JVM的內部工做機制