成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java的NIO

mrcode / 877人閱讀

摘要:也支持鎖定部分內(nèi)容,使用即可,其中為時(shí),表明該鎖是一個(gè)共享鎖,可以允許多個(gè)縣城讀取文件,但阻止其他進(jìn)程獲得該文件的排他鎖。當(dāng)為時(shí),表明是一個(gè)排他鎖,它將鎖住對(duì)該文件的讀寫(xiě)。默認(rèn)獲取的是排他鎖。

Java的NIO

BufferedReader有一個(gè)特征,就是讀取輸入流中的數(shù)據(jù)時(shí),如果沒(méi)有讀到有效數(shù)據(jù),程序?qū)⒃诖颂幾枞摼€程的執(zhí)行(使用InputStream的read方法從流中讀取數(shù)據(jù)時(shí),也有這樣的特性),java.io下面的輸入輸出流都是阻塞式的。不僅如此,傳統(tǒng)的輸入輸出流都是通過(guò)字節(jié)的移動(dòng)來(lái)處理的,及時(shí)我們不直接去處理字節(jié)流,單底層的實(shí)現(xiàn)還是依賴于字節(jié)處理,也就是說(shuō),面向流的輸入輸出系統(tǒng)一次只能處理一個(gè)字節(jié),因此面向流的輸入輸出系統(tǒng)通常效率都不高。

為了解決上面的問(wèn)題,NIO就出現(xiàn)了。NIO采用內(nèi)存映射文件來(lái)處理輸入輸出,NIO將文件或文件的一段區(qū)域映射到內(nèi)存中,這樣就可以像訪問(wèn)內(nèi)存一樣來(lái)訪問(wèn)文件了。(這種方式模擬了操作系統(tǒng)上虛擬內(nèi)存的概念),通過(guò)這種方式進(jìn)行輸入輸出要快得多。

Channel(通道)和Buffer(緩沖)是NIO中兩個(gè)核心對(duì)象。Channel是對(duì)傳統(tǒng)的輸入輸出系統(tǒng)的模擬,在NIO系統(tǒng)中所有的數(shù)據(jù)都需要通過(guò)通道傳輸,Channel與傳統(tǒng)的InputStream、OutputStream最大的區(qū)別就是提供了一個(gè)map()方法,通過(guò)它可以直接將“一塊數(shù)據(jù)”映射到內(nèi)存中。如果說(shuō)傳統(tǒng)IO是面向流的處理,那么NIO是面向塊的處理。

Buffer可以被理解為一個(gè)容器,它的本質(zhì)是一個(gè)數(shù)組,發(fā)送到Channel中所有的對(duì)象都必須首先放到Buffer中,從而Channel中讀取的數(shù)據(jù)也必須先放到Buffer中。Buffer既可以一次次從Channel取數(shù)據(jù),也可以使用Channel直接將文件的某塊數(shù)據(jù)映射成Buffer。

除了Channel和Buffer之外,NIO還提供了用于將Unicode字符串映射成字節(jié)序列以及逆映射操作的Charset類,也提供了用于支持非阻塞式輸入輸出的Selector類。

Buffer介紹

在Buffer中有三個(gè)重要的概念:

容量(capacity):表示Buffer的大小,創(chuàng)建后不能呢過(guò)改變;

界限(limit):第一個(gè)不能被讀寫(xiě)的緩沖區(qū)的位置,也就是后面的數(shù)據(jù)不能被讀寫(xiě);

位置(position):用于指明下一個(gè)可以被讀寫(xiě)的緩沖區(qū)位置索引。當(dāng)從Channel讀取數(shù)據(jù)的時(shí)候,position的值就等于讀到了多少數(shù)據(jù)。

Buffer的主要作用就是裝入數(shù)據(jù),然后輸出數(shù)據(jù)。當(dāng)裝入數(shù)據(jù)結(jié)束時(shí),調(diào)用flip()方法,該方法將limit設(shè)為position所在位置,將position的值設(shè)為0,為輸出數(shù)據(jù)做好準(zhǔn)備。當(dāng)輸出數(shù)據(jù)結(jié)束后,調(diào)用clear()方法,將position的值設(shè)為0,limit設(shè)為capacity,為下一次的裝入數(shù)據(jù)做準(zhǔn)備。

常用的Buffer是CharBuffer和ByteBuffer。

使用put()和get()方法進(jìn)行數(shù)據(jù)的放入和讀取,分為相對(duì)和絕對(duì)兩種:

相對(duì):從Buffer當(dāng)前position位置開(kāi)始讀取或者寫(xiě)入數(shù)據(jù),然后將position的值按處理元素的個(gè)數(shù)增加;

絕對(duì):直接根據(jù)索引向Buffer中讀取和寫(xiě)入數(shù)據(jù),使用絕對(duì)方式訪問(wèn)Buffer里的數(shù)據(jù)時(shí),不會(huì)影響position的值。

代碼示例

package com.wangjun.othersOfJava;

import java.nio.CharBuffer;

public class NIOBufferTest {

    public static void main(String[] args) {
        //創(chuàng)建CharBuffer
        CharBuffer cb = CharBuffer.allocate(8);
        System.out.println("capacity:" + cb.capacity());
        System.out.println("limit:" + cb.limit());
        System.out.println("position:" + cb.position());
        //放入元素
        cb.put("a");
        cb.put("b");
        cb.put("c");
        System.out.println("加入三個(gè)元素后,position:" + cb.position());
        cb.flip();
        System.out.println("執(zhí)行flip()后,limit:" + cb.limit());
        System.out.println("執(zhí)行flip()后,position:" + cb.position());
        System.out.println("取出第一個(gè)元素: " + cb.get());
        System.out.println("取出第一個(gè)元素后,position:" + cb.position());
        //調(diào)用clear方法
        cb.clear();
        System.out.println("執(zhí)行clear()后,limit:" + cb.limit());
        System.out.println("執(zhí)行clear()后,position:" + cb.position());
        System.out.println("執(zhí)行clear()后,數(shù)據(jù)沒(méi)有清空,第三個(gè)值是:" + cb.get(2));
        System.out.println("執(zhí)行絕對(duì)讀取后,position:" + cb.position());
    }

}

通過(guò)allocate方法創(chuàng)建的是普通Buffer,還可以通過(guò)allocateDirect方法來(lái)創(chuàng)建直接Buffer,雖然創(chuàng)建成本比較高,但是讀寫(xiě)快。因此適用于長(zhǎng)期生存的Buffer,使用方法和普通Buffer類似。注意,只有ByteBuffer提供了此方法,其他類型的想用,可以將該Buffer轉(zhuǎn)成其他類型的Buffer。

Channel(通道)介紹

Channel類似傳統(tǒng)的流對(duì)象,主要區(qū)別如下:

Channel可以直接將指定文件的部分或全部直接映射成Buffer。

程序不能直接訪問(wèn)Channel中的數(shù)據(jù),只能通過(guò)Buffer交互。

所有的Channel都不應(yīng)該通過(guò)構(gòu)造器來(lái)創(chuàng)建,而是通過(guò)傳統(tǒng)的InputStream、OutputStream的getChannel()方法來(lái)返回對(duì)應(yīng)的Channel,不同的節(jié)點(diǎn)流獲取的Channel不一樣,比如FileInputStream返回的是FileChannel。

Channel常用的方法有三類:map()、read()、write()。map方法將Channel對(duì)應(yīng)的部分或全部數(shù)據(jù)映射成ByteBuffer;read和write方法都有一系列的重載形式,這些方法用于從Buffer中讀取/寫(xiě)入數(shù)據(jù)。

代碼示例

package com.wangjun.othersOfJava;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

/*
 * 將FileChannel的全部數(shù)據(jù)映射成ByteBuffer
 */
public class NIOChannelTest {

    public static void main(String[] args) throws Exception {
        File f = new File("NIOChannelTest.md");
        //java7新特性try括號(hào)內(nèi)的資源會(huì)在try語(yǔ)句結(jié)束后自動(dòng)釋放,前提是這些可關(guān)閉的資源必須實(shí)現(xiàn) java.lang.AutoCloseable 接口。
        try(
            FileChannel inChannel = new FileInputStream(f).getChannel();
            FileChannel outChannel = new FileOutputStream("a.md").getChannel();
                ){
            //將FileChannel的全部數(shù)據(jù)映射成ByteBuffer
            //map方法的三個(gè)參數(shù):1映射模式;2,3控制將哪些數(shù)據(jù)映射成ByteBuffer
            MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, f.length());
            //直接將buffer的數(shù)據(jù)全部輸出,完成文件的復(fù)制: NIOChannelTest.md -> a.md
            outChannel.write(buffer);
            
            //以下為了輸出文件字符串內(nèi)容
            //使用GBK字符集來(lái)創(chuàng)建解碼器
            Charset charset = Charset.forName("GBK");
            //復(fù)原limit和position的位置
            buffer.clear();
            //創(chuàng)建解碼器
            CharsetDecoder decoder = charset.newDecoder();
            //使用解碼器將ByteBuffer轉(zhuǎn)成CharBuffer
            CharBuffer charBuffer = decoder.decode(buffer);
            System.out.println(charBuffer);
        }
    }

}

除了上面的一次性取數(shù)據(jù),也可以分多次取數(shù)據(jù)

//如果Channel對(duì)應(yīng)的文件過(guò)大,使用map方法一次性將所有文件內(nèi)容映射到內(nèi)存中可能會(huì)因此性能下降
//這時(shí)候我們可以適應(yīng)Channel和Buffer進(jìn)行多次重復(fù)取值
public static void getDataByArray() throws Exception {
  try(
    //創(chuàng)建文件輸入流
    FileInputStream fileInputStream = new FileInputStream("NIOChannelTest.md");
    FileChannel fileChannel = fileInputStream.getChannel();
  ){
    //定義一個(gè)ByteBuffer對(duì)象,用于重復(fù)取水
    ByteBuffer bbuff = ByteBuffer.allocate(64);
    while(fileChannel.read(bbuff) != -1) {
      bbuff.flip();
      Charset charset = Charset.forName("GBK");
      //創(chuàng)建解碼器
      CharsetDecoder decoder = charset.newDecoder();
      //使用解碼器將ByteBuffer轉(zhuǎn)成CharBuffer
      CharBuffer charBuffer = decoder.decode(bbuff);
      System.out.println(charBuffer);
      //為下一次讀取數(shù)據(jù)做準(zhǔn)備
      bbuff.clear();
    }
  }
}
文件鎖

在NIO中,Java提供了文件鎖的支持,使用FileLock來(lái)支持文件鎖定功能,在FileChannel中提供lock()/tryLock()方法來(lái)獲取文件鎖FileLock對(duì)象,從而鎖定文件。lock和tryLock的區(qū)別是前者無(wú)法得到文件鎖的時(shí)候會(huì)阻塞,后者不會(huì)阻塞。也支持鎖定部分內(nèi)容,使用lock(long position, long size, boolean shared)即可,其中shared為true時(shí),表明該鎖是一個(gè)共享鎖,可以允許多個(gè)縣城讀取文件,但阻止其他進(jìn)程獲得該文件的排他鎖。當(dāng)shared為false時(shí),表明是一個(gè)排他鎖,它將鎖住對(duì)該文件的讀寫(xiě)。

默認(rèn)獲取的是排他鎖。

代碼示例

package com.wangjun.othersOfJava;

import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class FileLockTest {
    public static void main(String[] args) throws Exception {
        try(
            FileOutputStream fos = new FileOutputStream("a.md");
            FileChannel fc = fos.getChannel();
                ){
            //使用非阻塞方式對(duì)指定文件加鎖
            FileLock lock = fc.tryLock();
            Thread.sleep(3000);
            lock.release();//釋放鎖
        }
    }
}
Java的NIO2

Java7對(duì)原來(lái)的NIO進(jìn)行了重大改進(jìn):

提供了全面的文件IO和文件系統(tǒng)訪問(wèn)支持;

基于異步Channel的IO。

這里先簡(jiǎn)單介紹一下對(duì)文件系統(tǒng)的支持,后續(xù)繼續(xù)學(xué)習(xí)。

NIO2提供了一下接口和工具類:

Path接口:通過(guò)和Paths工具類結(jié)合使用產(chǎn)生Path對(duì)象,可以獲取文件根路徑、絕對(duì)路徑、路徑數(shù)量等;

Files工具類:提供了很多靜態(tài)方法,比如復(fù)制文件、一次性讀取文件所有行、判斷是否為隱藏文件、判斷文件大小、遍歷文件和子目錄、訪問(wèn)文件屬性等;

FileVisitor接口:代表一個(gè)文件訪問(wèn)器,F(xiàn)iles工具類使用walkFileTree方法遍歷文件和子目錄時(shí),都會(huì)觸發(fā)FileVisitor中相應(yīng)的方法,比如訪問(wèn)目錄之前、之后,訪問(wèn)文件時(shí),訪問(wèn)文件失敗時(shí);

WatchService:監(jiān)控文件的變化;

NIO和IO的區(qū)別

Java的NIO提供了與標(biāo)準(zhǔn)IO不同的工作方式:

Channels and Buffers(通道和緩沖區(qū)):標(biāo)準(zhǔn)的IO基于字節(jié)流和字符流進(jìn)行操作的,沒(méi)有被緩存在任何地方,而NIO是基于通道(Channel)和緩沖區(qū)(Buffer)進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫(xiě)入到通道中,因此可以前后移動(dòng)流中的數(shù)據(jù);

Asynchronous IO(異步IO):Java NIO可以讓你異步的使用IO,例如:當(dāng)線程從通道讀取數(shù)據(jù)到緩沖區(qū)時(shí),線程還是可以進(jìn)行其他事情。當(dāng)數(shù)據(jù)被寫(xiě)入到緩沖區(qū)時(shí),線程可以繼續(xù)處理它。從緩沖區(qū)寫(xiě)入通道也類似。因?yàn)镹IO將阻塞交給了后臺(tái)線程執(zhí)行。而IO是阻塞的;

Selectors(選擇器):選擇器允許一個(gè)多帶帶的線程可以監(jiān)聽(tīng)多個(gè)數(shù)據(jù)通道((網(wǎng)絡(luò)連接或文件),你可以注冊(cè)多個(gè)通道使用一個(gè)選擇器,然后使用一個(gè)多帶帶的線程來(lái)“選擇”通道:這些通道里已經(jīng)有可以處理的輸入,或者選擇已準(zhǔn)備寫(xiě)入的通道。這種選擇機(jī)制,使得一個(gè)多帶帶的線程很容易來(lái)管理多個(gè)通道。但付出的代價(jià)是解析數(shù)據(jù)可能會(huì)比從一個(gè)阻塞流中讀取數(shù)據(jù)更復(fù)雜。?

使用場(chǎng)景

NIO

優(yōu)勢(shì)在于一個(gè)線程管理多個(gè)通道;但是數(shù)據(jù)的處理將會(huì)變得復(fù)雜;

如果需要管理同時(shí)打開(kāi)的成千上萬(wàn)個(gè)連接,這些連接每次只是發(fā)送少量的數(shù)據(jù),采用這種;

傳統(tǒng)的IO

適用于一個(gè)線程管理一個(gè)通道的情況;因?yàn)槠渲械牧鲾?shù)據(jù)的讀取是阻塞的;

如果需要管理同時(shí)打開(kāi)不太多的連接,這些連接會(huì)發(fā)送大量的數(shù)據(jù);

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71093.html

相關(guān)文章

  • Java NIO 系列教程

    摘要:異步可以讓你異步的使用,例如當(dāng)線程從通道讀取數(shù)據(jù)到緩沖區(qū)時(shí),線程還是可以進(jìn)行其他事情。當(dāng)數(shù)據(jù)被寫(xiě)入到緩沖區(qū)時(shí),線程可以繼續(xù)處理它。因此,單個(gè)的線程可以監(jiān)聽(tīng)多個(gè)數(shù)據(jù)通道。下面是系列文章的目錄概述通道之間的數(shù)據(jù)傳輸與原文譯者郭蕾校對(duì)方騰飛 Java NIO(New IO)是一個(gè)可以替代標(biāo)準(zhǔn)Java IO API的IO API(從Java 1.4開(kāi)始),Java NIO提供了與標(biāo)準(zhǔn)IO不同的...

    fanux 評(píng)論0 收藏0
  • Java NIO 概覽

    摘要:線程之間的切換對(duì)于操作系統(tǒng)來(lái)說(shuō)是昂貴的。因此,單線程可以監(jiān)視多個(gè)通道中的數(shù)據(jù)。當(dāng)方法返回后,線程可以處理這些事件。 一 NIO簡(jiǎn)介 Java NIO 是 java 1.4 之后新出的一套IO接口,這里的的新是相對(duì)于原有標(biāo)準(zhǔn)的Java IO和Java Networking接口。NIO提供了一種完全不同的操作方式。 NIO中的N可以理解為Non-blocking,不單純是New。 它支持面...

    chemzqm 評(píng)論0 收藏0
  • 關(guān)于Java IO與NIO知識(shí)都在這里

    摘要:從通道進(jìn)行數(shù)據(jù)寫(xiě)入創(chuàng)建一個(gè)緩沖區(qū),填充數(shù)據(jù),并要求通道寫(xiě)入數(shù)據(jù)。三之通道主要內(nèi)容通道介紹通常來(lái)說(shuō)中的所有都是從通道開(kāi)始的。從中選擇選擇器維護(hù)注冊(cè)過(guò)的通道的集合,并且這種注冊(cè)關(guān)系都被封裝在當(dāng)中停止選擇的方法方法和方法。 由于內(nèi)容比較多,我下面放的一部分是我更新在我的微信公眾號(hào)上的鏈接,微信排版比較好看,更加利于閱讀。每一篇文章下面我都把文章的主要內(nèi)容給列出來(lái)了,便于大家學(xué)習(xí)與回顧。 Ja...

    Riddler 評(píng)論0 收藏0
  • Java NIO 前生今世 之一 簡(jiǎn)介

    摘要:簡(jiǎn)介是由引進(jìn)的異步由以下幾個(gè)核心部分組成和的對(duì)比和的區(qū)別主要體現(xiàn)在三個(gè)方面基于流而基于操作是阻塞的而操作是非阻塞的沒(méi)有概念而有概念基于與基于傳統(tǒng)的是面向字節(jié)流或字符流的而在中我們拋棄了傳統(tǒng)的流而是引入了和的概念在中我只能從中讀取數(shù)據(jù)到中或?qū)? 簡(jiǎn)介 Java NIO 是由 Java 1.4 引進(jìn)的異步 IO.Java NIO 由以下幾個(gè)核心部分組成: Channel Buffer Se...

    李義 評(píng)論0 收藏0
  • 動(dòng)力節(jié)點(diǎn)JavaNIO教程,輕松攻破Java NIO技術(shù)壁壘

    摘要:學(xué)習(xí)和掌握技術(shù)已經(jīng)不是一個(gè)攻城獅的加分技能,而是一個(gè)必備技能。是雙向的,不僅可以讀取數(shù)據(jù)還能保存數(shù)據(jù),程序不能直接讀寫(xiě)通道,只與緩沖區(qū)交互為了讓大家不被高并發(fā)與大量連接處理問(wèn)題所困擾,動(dòng)力節(jié)點(diǎn)推出了高效處理模型應(yīng)用教程。 大家肯定了解Java IO, 但是對(duì)于NIO一般是陌生的,而現(xiàn)在使用到NIO的場(chǎng)景越來(lái)越多,很多技術(shù)框...

    ralap 評(píng)論0 收藏0
  • Netty序章之BIO NIO AIO演變

    摘要:后改良為用線程池的方式代替新增線程,被稱為偽異步。最大的問(wèn)題是阻塞,同步。每次請(qǐng)求都由程序執(zhí)行并返回,這是同步的缺陷。這些都會(huì)被注冊(cè)在多路復(fù)用器上。多路復(fù)用器提供選擇已經(jīng)就緒狀態(tài)任務(wù)的能力。并沒(méi)有采用的多路復(fù)用器,而是使用異步通道的概念。 Netty是一個(gè)提供異步事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用框架,用以快速開(kāi)發(fā)高性能、高可靠的網(wǎng)絡(luò)服務(wù)器和客戶端程序。Netty簡(jiǎn)化了網(wǎng)絡(luò)程序的開(kāi)發(fā),是很多框架和公司...

    VincentFF 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<