NIO.2-異步文件通道-通過handler處理

異步文件通道-通過handler處理

AsynchronousFileChannel

使用 Future 對象的替代機(jī)制,是向異步操作注冊一個 callback 赂弓。接口 CompletionHandler 有兩個方法:

  • void completed(V result, A attachment) // 在任務(wù)完成結(jié)果中具有類型 V 時執(zhí)行。
  • void failed(Throwable e, A attachment) // 在任務(wù)由于 Throwable e 而失敗時執(zhí)行推姻。

兩個方法的附件參數(shù)都是一個傳遞到異步操作的對象再膳。如果相同的對象用于多個操作削祈,其可用于追蹤哪個操作已完成桥狡。

Open 命令

我們來看一個使用 AsynchronousFileChannel 類的例子卦绣。可通過將 java.nio.file.Path 對象傳遞到靜態(tài) open() 方法中咙崎,來創(chuàng)建一個新的通道:

AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Paths.get("myfile"));

FileChannel 的新 open 命令
用于異步通道的 open 命令格式已被移植到 FileChannel 類仗处。在 NIO 中眯勾,通過在 FileInputStream、FileOutputStream婆誓、或者 RandomAccessFile 上調(diào)用 getChannel() 來獲取 FileChannel吃环。借助 NIO.2,可利用 open() 方法來直接創(chuàng)建 FileChannel洋幻。

默認(rèn)情況下郁轻,該文件已打開以供讀取。open() 方法可利用附加選項來指定如何打開該文件。例如好唯,此調(diào)用打開文件以供讀取或?qū)懭虢吣绻匾獙?chuàng)建該文件,并在通道關(guān)閉或者 JVM 終止時嘗試刪除文件:

fileChannel = AsynchronousFileChannel.open(
            Paths.get("afile"), 
            StandardOpenOption.READ, 
            StandardOpenOption.WRITE,
            StandardOpenOption.CREATE, 
            StandardOpenOption.DELETE_ON_CLOSE
            );

替代方法 open() 提供了對通道的更好的控制骑篙,允許設(shè)置文件屬性蜕提。

實現(xiàn)一個完成處理程序

接下來,可將這些寫入文件靶端,寫入完成后谎势,就可執(zhí)行一些操作。 首先要構(gòu)造一個封裝了 “ something ” 的 CompletionHandler :

// 創(chuàng)建完成處理程序
CompletionHandler<Integer, Object> handler =
    new CompletionHandler<Integer, Object>() {
        @Override
        public void completed(Integer result, Object attachment) {
            System.out.println(attachment + " completed with " + result + " bytes written");
        }
        @Override
        public void failed(Throwable e, Object attachment) {
            System.err.println(attachment + " failed with:");
            e.printStackTrace();
        }
    };

現(xiàn)在可以進(jìn)行寫入:

fileChannel.write(ByteBuffer.wrap(bytes), 0, "Write operation 1", handler);

write() 方法參數(shù):

  • 包含要寫入內(nèi)容的 ByteBuffer
  • 文件中的絕對位置
  • 要傳遞給完成處理程序方法的附件對象
  • 完成處理程序

操作必須給出進(jìn)行讀或?qū)懙奈募械慕^對位置杨名。文件具有內(nèi)部位置標(biāo)記脏榆,來指出讀/寫發(fā)生的位置,這樣做沒有意義台谍,因為在上一個操作完成之前须喂,就可以啟動新操作,它們的發(fā)生順序無法得到保證典唇。由于相同的原因镊折,在 AsynchronousFileChannel API 中沒有用于設(shè)置或查詢位置的方法胯府,在 FileChannel 中同樣也沒有介衔。

除了讀寫方法之外,還支持異步鎖定方法骂因,因此炎咖,如果當(dāng)前有其他線程保持鎖定時,可對文件進(jìn)行執(zhí)行訪問鎖定寒波,而不必在當(dāng)前線程中鎖定(或者利用 tryLock 輪詢)乘盼。


寫文件:

public class FileWriterEnd {

    public void write() {
        try {
            final AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
                    Paths.get("writeshow.log"),
                    StandardOpenOption.WRITE,
                    //StandardOpenOption.DELETE_ON_CLOSE,
                    StandardOpenOption.CREATE
            );

            CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {
                @Override
                public void completed(Integer result, Object attachment) {
                    System.out.println(attachment + "S>>> completed with " + result + " bytes written");
                }

                @Override
                public void failed(Throwable e, Object attachment) {
                    if (e instanceof AsynchronousCloseException) {
                        System.out.println("S>>> File was closed before " + attachment + " executed");
                    } else {
                        System.err.println("S>>> " + attachment + " failed with:");
                        e.printStackTrace();
                    }
                }
            };

            int count = 0;
            int position = 0;
            while (count < 10) {
                byte[] contents = "hello  ".getBytes();
                System.out.println("S>>> Initiating write operation " + count);
                fileChannel.write(ByteBuffer.wrap(contents), position , "Write operation "+count + " ", handler);
                position += contents.length;
                count++;

                Thread.sleep(1000);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new FileWriterEnd().write();
    }
}
寫入

讀文件:

public class FileReaderEnd {
    
    public void read() {
        try {
            final AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
                    Paths.get("writeshow.log"),
                    StandardOpenOption.READ
            );
            
            final ByteBuffer buffer = ByteBuffer.allocate(7);
            CompletionHandler<Integer, Object> handler= new CompletionHandler<Integer, Object>(){
                @Override
                public void completed(Integer result, Object attachment) {
                    System.out.println("C))) Read operation completed, file contents is: " + new String(buffer.array()));
                    clearUp();
                }
                @Override
                public void failed(Throwable e, Object attachment) {
                    System.err.println("C))) Exception performing write");
                    e.printStackTrace();
                    clearUp();
                }

                private void clearUp() {
                    try {
                        fileChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };


            System.out.println("C))) Initiating read operation");
            //Future<Integer> future = fileChannel.read(buffer, 0); // 
            //System.out.println("future : " + future.get());
            fileChannel.read(buffer, 0, null, handler);

            Thread.sleep(3*1000); // 由于handler處理是異步的,防止主線程過早結(jié)束俄烁,等待handler處理

        } catch (IOException e) {
            e.printStackTrace();
        } /*catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }*/ catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new FileReaderEnd().read();
    }

}
讀取
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绸栅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子页屠,更是在濱河造成了極大的恐慌粹胯,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辰企,死亡現(xiàn)場離奇詭異风纠,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)牢贸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門竹观,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事臭增《矗” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵速址,是天一觀的道長玩焰。 經(jīng)常有香客問我,道長芍锚,這世上最難降的妖魔是什么昔园? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮并炮,結(jié)果婚禮上默刚,老公的妹妹穿的比我還像新娘。我一直安慰自己逃魄,他們只是感情好荤西,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伍俘,像睡著了一般邪锌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上癌瘾,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天觅丰,我揣著相機(jī)與錄音,去河邊找鬼妨退。 笑死妇萄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咬荷。 我是一名探鬼主播冠句,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼幸乒!你這毒婦竟也來了懦底?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤罕扎,失蹤者是張志新(化名)和其女友劉穎聚唐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體壳影,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拱层,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了宴咧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片根灯。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出烙肺,到底是詐尸還是另有隱情纳猪,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布桃笙,位于F島的核電站氏堤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏搏明。R本人自食惡果不足惜鼠锈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望星著。 院中可真熱鬧购笆,春花似錦、人聲如沸虚循。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽横缔。三九已至铺遂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茎刚,已是汗流浹背襟锐。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留斗蒋,地道東北人捌斧。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓笛质,卻偏偏與公主長得像泉沾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子妇押,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)自 http://www.ibm.com/developerworks/cn/education/java/j-...
    抓兔子的貓閱讀 2,313評論 0 22
  • Java NIO(New IO)是從Java 1.4版本開始引入的一個新的IO API跷究,可以替代標(biāo)準(zhǔn)的Java I...
    JackChen1024閱讀 7,556評論 1 143
  • (轉(zhuǎn)載說明:本文非原創(chuàng),轉(zhuǎn)載自http://ifeve.com/java-nio-all/) Java NIO: ...
    數(shù)獨(dú)題閱讀 808評論 0 3
  • (轉(zhuǎn)載說明:本文非原創(chuàng),轉(zhuǎn)載自http://ifeve.com/java-nio-all/) Java NIO: ...
    柳岸閱讀 822評論 0 3
  • NIO 并發(fā)編程網(wǎng) - ifeve.comJava NIO系列教程 筆記 http://ifeve.com...
    梓青閱讀 597評論 0 0