java中 immutable,future,nio
什么是Future?
用過Java并發包的朋友或許對Future (interface)?已經比較熟悉了,其實Future?本身是一種被廣泛運用的并發設計模式,可在很大程度上簡化需要數據流同步的并發應用開發。在一些領域語言(如Alice ML?)中甚至直接于語法層面支持Future。
這里就以java.util.concurrent.Future?為例簡單說一下Future的具體工作方式。Future對象本身可以看作是一個顯式的引用,一個對異步處理結果的引用。由于其異步性質,在創建之初,它所引用的對象可能還并不可用(比如尚在運算中,網絡傳輸中或等待中)。這時,得到Future的程序流程如果并不急于使用Future所引用的對象,那么它可以做其它任何想做的事兒,當流程進行到需要Future背后引用的對象時,可能有兩種情況:
- 希望能看到這個對象可用,并完成一些相關的后續流程。如果實在不可用,也可以進入其它分支流程。
- “沒有你我的人生就會失去意義,所以就算海枯石爛,我也要等到你。”(當然,如果實在沒有毅力枯等下去,設一個超時也是可以理解的)
對于前一種情況,可以通過調用Future.isDone()判斷引用的對象是否就緒,并采取不同的處理;而后一種情況則只需調用get()或
get(long timeout, TimeUnit unit)通過同步阻塞方式等待對象就緒。實際運行期是阻塞還是立即返回就取決于get()的調用時機和對象就緒的先后了。
簡單而言,Future模式可以在連續流程中滿足數據驅動的并發需求,既獲得了并發執行的性能提升,又不失連續流程的簡潔優雅。
在Java中,如果需要設定代碼執行的最長時間,即超時,可以用Java線程池ExecutorService類配合Future接口來實現。 Future接口是Java標準API的一部分,在java.util.concurrent包中。Future接口是Java線程Future模式的實現,可以來進行異步計算。
Future模式可以這樣來描述:我有一個任務,提交給了Future,Future替我完成這個任務。期間我自己可以去做任何想做的事情。一段時間之后,我就便可以從Future那兒取出結果。就相當于下了一張訂貨單,一段時間后可以拿著提訂單來提貨,這期間可以干別的任何事情。其中Future 接口就是訂貨單,真正處理訂單的是Executor類,它根據Future接口的要求來生產產品。
Future接口提供方法來檢測任務是否被執行完,等待任務執行完獲得結果,也可以設置任務執行的超時時間。這個設置超時的方法就是實現Java程序執行超時的關鍵。
Java NIO?
?? IO 是主存和外部設備拷貝數據的過程。IO 是操作系統的底層功能實現,底層通過 I/O 指令進行完成。
?? NIO是java new IO的簡稱,是JDK 1.4提供的新特性,主要包括以下幾個方面:
?
– ?? ?為所有的原始類型提供緩存支持。
– ??? 字符集編碼解碼解決方案。
– ??? Channel :一個新的原始 I/O 抽象。
– ??? 支持鎖和內存映射文件的文件訪問接口。
– ??? 提供多路 (non-bloking) 非阻塞式的高伸縮性網絡 I/O 。
?
Buffer Channel
??? Buffer? 是一塊連續的內存塊,是NIO讀寫數據的中轉站
??? Channle 數據的源頭或者數據的目的地,用于向 buffer 提供數據或者讀取 buffer 數據 ,buffer 對象的唯一接口
?
?在Buffer的實現過程中,主要由 position,limit,capacity 三個變量來控制讀寫的過程
?Position 當前寫入或讀入單位數據數量
?limit????? 代表可以寫入或者讀入的最大數據量和Buffer容量大小是相同的
?capacity Buffer容量
?
Charset 字符編碼
?
?? 字符編碼解碼 : 字節碼本身只是一些數字,放到正確的上下文中被正確被解析。向 ByteBuffer 中存放數據時需要考慮字符集的編碼方式,讀取 ByteBuffer 數據時也涉及對字符集解碼
Java.nio.charset 提供了編碼解碼一套解決方案,以http為例,向百度發送請求,并正常的顯示。使用到了Charset編碼
1 package nio.readpage; 2 3 import java.nio.ByteBuffer; 4 import java.nio.channels.SocketChannel; 5 import java.nio.charset.Charset; 6 import java.net.InetSocketAddress; 7 import java.io.IOException; 8 public class BaiduReader { 9 private Charset charset = Charset.forName("GBK");// 創建GBK字符集 10 private SocketChannel channel; 11 public void readHTMLContent() { 12 try { 13 InetSocketAddress socketAddress = new InetSocketAddress( 14 "www.baidu.com", 80); 15 //step1:打開連接 16 channel = SocketChannel.open(socketAddress); 17 //step2:發送請求,使用GBK編碼 18 channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n")); 19 //step3:讀取數據 20 ByteBuffer buffer = ByteBuffer.allocate(1024);// 創建1024字節的緩沖 21 while (channel.read(buffer) != -1) { 22 buffer.flip();// flip方法在讀緩沖區字節操作之前調用。 23 System.out.println(charset.decode(buffer)); 24 // 使用Charset.decode方法將字節轉換為字符串 25 buffer.clear();// 清空緩沖 26 } 27 } catch (IOException e) { 28 System.err.println(e.toString()); 29 } finally { 30 if (channel != null) { 31 try { 32 channel.close(); 33 } catch (IOException e) { 34 } 35 } 36 } 37 } 38 public static void main(String[] args) { 39 new BaiduReader().readHTMLContent(); 40 } 41 }?
?
?一個常見的網絡 IO 通訊流程:
?? Open(打開Socket連接)->Accept(接受連接)->Read(讀取請求)->Send(發送響應)->Close(關閉連接)
?? 在Accpet還沒有帶來之前,會發生阻塞,程序掛起,放棄CPU資源
?? 若數據還沒有準備好,Read也會發生阻塞,程序掛起,放棄CPU資源
? 阻塞式網絡IO的特點:多線程處理多個連接,每個線程都有自己的占空間,并占用一些CPU資源,當程序運行所需要的外部資源還沒有準備好的時候,
? 程序會掛起,放棄CPU資源,轉而去執行其他的程序。這樣的結果是發生大量的上下文切換。
?
下面有個隱喻:
一輛從 A 開往 B 的公共汽車上,路上有很多點可能會有人下車。司機不知道哪些點會有哪些人會下車,對于需要下車的人,如何處理更好?
?
1. 司機過程中定時詢問每個乘客是否到達目的地,若有人說到了,那么司機停車,乘客下車。 ( 類似阻塞式 )
2. 每個人告訴售票員自己的目的地,然后睡覺,司機只和售票員交互,到了某個點由售票員通知乘客下車。 ( 類似非阻塞 )
?
很顯然,每個人要到達某個目的地可以認為是一個線程,司機可以認為是 CPU 。在阻塞式里面,每個線程需要不斷的輪詢,上下文切換,以達到找到目的地的結果。而在非阻塞方式里,每個乘客 ( 線程 ) 都在睡覺 ( 休眠 ) ,只在真正外部環境準備好了才喚醒,這樣的喚醒肯定不會阻塞。
?
?非阻塞的原理
??? 1? 把整個過程切換成小任務,通過任務間協作完成
??? 2 由一個專門的線程處理所有的IO事件,并負責分發
??? 3 事件驅動機制,事件到來的時候觸發,而不是同步的去檢測
??? 4 線程通訊 多線程之間通過wait 和notify 進行數據通信,保證每次的上下文切換都是有意義的
?
?
?
Java中很多class都是immutable,像String,Integer等,它們通常用來作為Map的key.
那么在實現自定義的Immutable的Class的時候,應該注意哪些要點呢?
a)Class 應該定義成final,避免被繼承。
b)所有的成員變量應該被定義成final。
c)不要提供可以改變類狀態(成員變量)的方法。【get 方法不要把類里的成員變量讓外部客服端引用,當需要訪問成員變量時,返回成員變量的copy】
d)構造函數不要引用外部可變對象。如果需要引用外部可以變量,應該在構造函數里進行defensive copy。
?
?
an immutable object is an object whose state cannot be modified after it is created.
?
不可變對象一旦被創建就它的狀態就不能被修改。
?
A classic example of an immutable object is an instance of the Java String class.
不可變對象的一個經典的例子是String類的實例。
?
Java代碼 ??
The method toLowerCase() will not change the data "ABC" that s contains.
Instead, a new String object is instantiated(被實例化 ) and given the data "abc" during its construction.
?
A reference to this String object is returned by the toLowerCase() method.
?
To make the String s contain the data "abc", a different approach is needed.
?
?
?
Java代碼 ??
?
Now the String s references a new String object that contains "abc". The String class's methods never affect the data that a String object contains.
?
For an object to be immutable, there has to be no way to change fields, mutable or not, and to access fields that are mutable.
?
Here is an example of a mutable object.
?
?
Java代碼 ??
?
An instance of this class is not immutable: one can add or remove items either by obtaining the field items by calling getItems() or by retaining(保留,保持 ) a reference to the List object passed when an object of this class is created.
?
The following change partially solves this problem. In the ImmutableCart class, the list is immutable: you cannot add or remove items.
?
However, there is no guarantee that the items are also immutable.
?
One solution is to use the decorator pattern as a wrapper around each of the list's items to make them also immutable.
?
?
?
Java代碼 ??
?運行拋出異常:
?
Exception in thread "main" java.lang.UnsupportedOperationException
?
?
public?class?Immutable?
{?
??private?int?data;?
??public?Immutable(int?initVal)?
??{?
????data=initVal;?
??}?
??public?int?read()?
??{?
????return?data;?
??}?
??public?Immutable?quadruple()?
??{?
????return?new?Immutable(data*4);?
??}?
}
轉載于:https://www.cnblogs.com/WayneZeng/p/3358457.html
總結
以上是生活随笔為你收集整理的java中 immutable,future,nio的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何打造高性能Web应用
- 下一篇: “数据分析”如何作用于“用户研究”?--