最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java NIO寫(xiě)大文件對(duì)比(win7和mac)

 更新時(shí)間:2019年07月10日 09:50:49   作者:優(yōu)雅先生  
這篇文章主要介紹了Java NIO寫(xiě)大文件對(duì)比(win7和mac),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

測(cè)試說(shuō)明

寫(xiě)2G文件,分批次寫(xiě)入,每批次寫(xiě)入128MB;

分別在Win7系統(tǒng)(3G內(nèi)存,雙核,32位,T系列處理器)和MacOS系統(tǒng)(8G內(nèi)存,四核,64位,i7系列處理器)下運(yùn)行測(cè)試。理論上跟硬盤(pán)類(lèi)型和配置也有關(guān)系,這里不再貼出了。

測(cè)試代碼

package rwbigfile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.channels.ReadableByteChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;

import util.StopWatch;

/**
 * NIO寫(xiě)大文件比較
 * @author Will
 * 
 */
public class WriteBigFileComparison {

	// data chunk be written per time
	private static final int DATA_CHUNK = 128 * 1024 * 1024; 

	// total data size is 2G
	private static final long LEN = 2L * 1024 * 1024 * 1024L; 

	
	public static void writeWithFileChannel() throws IOException {
		File file = new File("e:/test/fc.dat");
		if (file.exists()) {
			file.delete();
		}

		RandomAccessFile raf = new RandomAccessFile(file, "rw");
		FileChannel fileChannel = raf.getChannel();

		byte[] data = null;
		long len = LEN;
		ByteBuffer buf = ByteBuffer.allocate(DATA_CHUNK);
		int dataChunk = DATA_CHUNK / (1024 * 1024);
		while (len >= DATA_CHUNK) {
			System.out.println("write a data chunk: " + dataChunk + "MB");

			buf.clear(); // clear for re-write
			data = new byte[DATA_CHUNK];
			for (int i = 0; i < DATA_CHUNK; i++) {
				buf.put(data[i]);
			}

			data = null;

			buf.flip(); // switches a Buffer from writing mode to reading mode
			fileChannel.write(buf);
			fileChannel.force(true);

			len -= DATA_CHUNK;
		}

		if (len > 0) {
			System.out.println("write rest data chunk: " + len + "B");
			buf = ByteBuffer.allocateDirect((int) len);
			data = new byte[(int) len];
			for (int i = 0; i < len; i++) {
				buf.put(data[i]);
			}

			buf.flip(); // switches a Buffer from writing mode to reading mode, position to 0, limit not changed
			fileChannel.write(buf);
			fileChannel.force(true);
			data = null;
		}

		fileChannel.close();
		raf.close();
	}

	/**
	 * write big file with MappedByteBuffer
	 * @throws IOException
	 */
	public static void writeWithMappedByteBuffer() throws IOException {
		File file = new File("e:/test/mb.dat");
		if (file.exists()) {
			file.delete();
		}

		RandomAccessFile raf = new RandomAccessFile(file, "rw");
		FileChannel fileChannel = raf.getChannel();
		int pos = 0;
		MappedByteBuffer mbb = null;
		byte[] data = null;
		long len = LEN;
		int dataChunk = DATA_CHUNK / (1024 * 1024);
		while (len >= DATA_CHUNK) {
			System.out.println("write a data chunk: " + dataChunk + "MB");

			mbb = fileChannel.map(MapMode.READ_WRITE, pos, DATA_CHUNK);
			data = new byte[DATA_CHUNK];
			mbb.put(data);

			data = null;

			len -= DATA_CHUNK;
			pos += DATA_CHUNK;
		}

		if (len > 0) {
			System.out.println("write rest data chunk: " + len + "B");

			mbb = fileChannel.map(MapMode.READ_WRITE, pos, len);
			data = new byte[(int) len];
			mbb.put(data);
		}

		data = null;
		unmap(mbb);  // release MappedByteBuffer
		fileChannel.close();
	}
	
	public static void writeWithTransferTo() throws IOException {
		File file = new File("e:/test/transfer.dat");
		if (file.exists()) {
			file.delete();
		}
		
		RandomAccessFile raf = new RandomAccessFile(file, "rw");
		FileChannel toFileChannel = raf.getChannel();
		
		long len = LEN;
		byte[] data = null;
		ByteArrayInputStream bais = null;
		ReadableByteChannel fromByteChannel = null;
		long position = 0;
		int dataChunk = DATA_CHUNK / (1024 * 1024);
		while (len >= DATA_CHUNK) {
			System.out.println("write a data chunk: " + dataChunk + "MB");
			
			data = new byte[DATA_CHUNK];
			bais = new ByteArrayInputStream(data);
			fromByteChannel = Channels.newChannel(bais);
			
			long count = DATA_CHUNK;
			toFileChannel.transferFrom(fromByteChannel, position, count);
			
			data = null;
			position += DATA_CHUNK;
			len -= DATA_CHUNK;
		}
		
		if (len > 0) {
			System.out.println("write rest data chunk: " + len + "B");

			data = new byte[(int) len];
			bais = new ByteArrayInputStream(data);
			fromByteChannel = Channels.newChannel(bais);
			
			long count = len;
			toFileChannel.transferFrom(fromByteChannel, position, count);
		}
		
		data = null;
		toFileChannel.close();
		fromByteChannel.close();
	}
	
	/**
	 * 在MappedByteBuffer釋放后再對(duì)它進(jìn)行讀操作的話(huà)就會(huì)引發(fā)jvm crash,在并發(fā)情況下很容易發(fā)生
	 * 正在釋放時(shí)另一個(gè)線(xiàn)程正開(kāi)始讀取,于是crash就發(fā)生了。所以為了系統(tǒng)穩(wěn)定性釋放前一般需要檢
	 * 查是否還有線(xiàn)程在讀或?qū)?
	 * @param mappedByteBuffer
	 */
	public static void unmap(final MappedByteBuffer mappedByteBuffer) {
		try {
			if (mappedByteBuffer == null) {
				return;
			}
			
			mappedByteBuffer.force();
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				@SuppressWarnings("restriction")
				public Object run() {
					try {
						Method getCleanerMethod = mappedByteBuffer.getClass()
								.getMethod("cleaner", new Class[0]);
						getCleanerMethod.setAccessible(true);
						sun.misc.Cleaner cleaner = 
								(sun.misc.Cleaner) getCleanerMethod
									.invoke(mappedByteBuffer, new Object[0]);
						cleaner.clean();
						
					} catch (Exception e) {
						e.printStackTrace();
					}
					System.out.println("clean MappedByteBuffer completed");
					return null;
				}
			});

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws IOException {
		StopWatch sw = new StopWatch();
		
		sw.startWithTaskName("write with file channel's write(ByteBuffer)");
		writeWithFileChannel();
		sw.stopAndPrint();
		
		sw.startWithTaskName("write with file channel's transferTo");
		writeWithTransferTo();
		sw.stopAndPrint();
		
		sw.startWithTaskName("write with MappedByteBuffer");
		writeWithMappedByteBuffer();
		sw.stopAndPrint();
	}

}

測(cè)試結(jié)果(Y軸是耗時(shí)秒數(shù))

  • 顯然writeWithMappedByteBuffer方式性能最好,且在硬件配置較高情況下優(yōu)勢(shì)越加明顯
  • 在硬件配置較低情況下,writeWithTransferTo比writeWithFileChannel性能稍好
  • 在硬件配置較高情況下,writeWithTransferTo和writeWithFileChannel的性能基本持平
  • 此外,注意writeWithMappedByteBuffer方式除了占用JVM堆內(nèi)存外,還要占用額外的native內(nèi)存(Direct Byte Buffer內(nèi)存)

內(nèi)存映射文件使用經(jīng)驗(yàn)

MappedByteBuffer需要占用“雙倍”的內(nèi)存(對(duì)象JVM堆內(nèi)存和Direct Byte Buffer內(nèi)存),可以通過(guò)-XX:MaxDirectMemorySize參數(shù)設(shè)置后者最大大小

不要頻繁調(diào)用MappedByteBuffer的force()方法,因?yàn)檫@個(gè)方法會(huì)強(qiáng)制OS刷新內(nèi)存中的數(shù)據(jù)到磁盤(pán),從而只能獲得些微的性能提升(相比IO方式),可以用后面的代碼實(shí)例進(jìn)行定時(shí)、定量刷新

如果突然斷電或者服務(wù)器突然Down,內(nèi)存映射文件數(shù)據(jù)可能還沒(méi)有寫(xiě)入磁盤(pán),這時(shí)就會(huì)丟失一些數(shù)據(jù)。為了降低這種風(fēng)險(xiǎn),避免用MappedByteBuffer寫(xiě)超大文件,可以把大文件分割成幾個(gè)小文件,但不能太?。ǚ駝t將失去性能優(yōu)勢(shì))

ByteBuffer的rewind()方法將position屬性設(shè)回為0,因此可以重新讀取buffer中的數(shù)據(jù);limit屬性保持不變,因此可讀取的字節(jié)數(shù)不變

ByteBuffer的flip()方法將一個(gè)Buffer由寫(xiě)模式切換到讀模式

ByteBuffer的clear()和compact()可以在我們讀完ByteBuffer中的數(shù)據(jù)后重新切回寫(xiě)模式。不同的是clear()會(huì)將position設(shè)置為0,limit設(shè)為capacity,換句話(huà)說(shuō)Buffer被清空了,但Buffer內(nèi)的數(shù)據(jù)并沒(méi)有被清空。如果Buffer中還有未被讀取的數(shù)據(jù),那調(diào)用clear()之后,這些數(shù)據(jù)會(huì)被“遺忘”,再寫(xiě)入就會(huì)覆蓋這些未讀數(shù)據(jù)。而調(diào)用compcat()之后,這些未被讀取的數(shù)據(jù)仍然可以保留,因?yàn)樗鼘⑺羞€未被讀取的數(shù)據(jù)拷貝到Buffer的左端,然后設(shè)置position為緊隨未讀數(shù)據(jù)之后,limit被設(shè)置為capacity,未讀數(shù)據(jù)不會(huì)被覆蓋

定時(shí)、定量刷新內(nèi)存映射文件到磁盤(pán)

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MappedFile {
	
	// 文件名
	private String fileName;

	// 文件所在目錄路徑
	private String fileDirPath;

	// 文件對(duì)象
	private File file;

	private MappedByteBuffer mappedByteBuffer;
	private FileChannel fileChannel;
	private boolean boundSuccess = false;

	// 文件最大只能為50MB
	private final static long MAX_FILE_SIZE = 1024 * 1024 * 50;
	
	// 最大的臟數(shù)據(jù)量512KB,系統(tǒng)必須觸發(fā)一次強(qiáng)制刷
	private long MAX_FLUSH_DATA_SIZE = 1024 * 512;

	// 最大的刷間隔,系統(tǒng)必須觸發(fā)一次強(qiáng)制刷
	private long MAX_FLUSH_TIME_GAP = 1000;

	// 文件寫(xiě)入位置
	private long writePosition = 0;

	// 最后一次刷數(shù)據(jù)的時(shí)候
	private long lastFlushTime;

	// 上一次刷的文件位置
	private long lastFlushFilePosition = 0;
	
	public MappedFile(String fileName, String fileDirPath) {
		super();
		this.fileName = fileName;
		this.fileDirPath = fileDirPath;
		this.file = new File(fileDirPath + "/" + fileName);
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}

	/**
	 * 
	 * 內(nèi)存映照文件綁定
	 * @return
	 */
	public synchronized boolean boundChannelToByteBuffer() {
		try {
			RandomAccessFile raf = new RandomAccessFile(file, "rw");
			this.fileChannel = raf.getChannel();
		} catch (Exception e) {
			e.printStackTrace();
			this.boundSuccess = false;
			return false;
		}

		try {
			this.mappedByteBuffer = this.fileChannel
					.map(FileChannel.MapMode.READ_WRITE, 0, MAX_FILE_SIZE);
		} catch (IOException e) {
			e.printStackTrace();
			this.boundSuccess = false;
			return false;
		}

		this.boundSuccess = true;
		return true;
	}
	
	/**
	 * 寫(xiě)數(shù)據(jù):先將之前的文件刪除然后重新
	 * @param data
	 * @return
	 */
	public synchronized boolean writeData(byte[] data) {
		
		return false;
	}
	
	/**
	 * 在文件末尾追加數(shù)據(jù)
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public synchronized boolean appendData(byte[] data) throws Exception {
		if (!boundSuccess) {
			boundChannelToByteBuffer();
		}
		
		writePosition = writePosition + data.length;
		if (writePosition >= MAX_FILE_SIZE) {  // 如果寫(xiě)入data會(huì)超出文件大小限制,不寫(xiě)入
			flush();
			writePosition = writePosition - data.length;
			System.out.println("File=" 
								+ file.toURI().toString() 
								+ " is written full.");
			System.out.println("already write data length:" 
								+ writePosition
								+ ", max file size=" + MAX_FILE_SIZE);
			return false;
		}

		this.mappedByteBuffer.put(data);

		// 檢查是否需要把內(nèi)存緩沖刷到磁盤(pán)
		if ( (writePosition - lastFlushFilePosition > this.MAX_FLUSH_DATA_SIZE)
			 ||
			 (System.currentTimeMillis() - lastFlushTime > this.MAX_FLUSH_TIME_GAP
			 && writePosition > lastFlushFilePosition) ) {
			flush();  // 刷到磁盤(pán)
		}
		
		return true;
	}

	public synchronized void flush() {
		this.mappedByteBuffer.force();
		this.lastFlushTime = System.currentTimeMillis();
		this.lastFlushFilePosition = writePosition;
	}

	public long getLastFlushTime() {
		return lastFlushTime;
	}

	public String getFileName() {
		return fileName;
	}

	public String getFileDirPath() {
		return fileDirPath;
	}

	public boolean isBundSuccess() {
		return boundSuccess;
	}

	public File getFile() {
		return file;
	}

	public static long getMaxFileSize() {
		return MAX_FILE_SIZE;
	}

	public long getWritePosition() {
		return writePosition;
	}

	public long getLastFlushFilePosition() {
		return lastFlushFilePosition;
	}

	public long getMAX_FLUSH_DATA_SIZE() {
		return MAX_FLUSH_DATA_SIZE;
	}

	public long getMAX_FLUSH_TIME_GAP() {
		return MAX_FLUSH_TIME_GAP;
	}

}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Mybatis-Plus和Mybatis的區(qū)別詳解

    Mybatis-Plus和Mybatis的區(qū)別詳解

    這篇文章主要介紹了Mybatis-Plus和Mybatis的區(qū)別,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • springboot如何獲取yml里面的屬性值

    springboot如何獲取yml里面的屬性值

    這篇文章主要介紹了springboot如何獲取yml里面的屬性值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • springboot+mongodb 實(shí)現(xiàn)按日期分組分頁(yè)查詢(xún)功能

    springboot+mongodb 實(shí)現(xiàn)按日期分組分頁(yè)查詢(xún)功能

    這篇文章主要介紹了springboot+mongodb 實(shí)現(xiàn)按日期分組分頁(yè)查詢(xún)功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07
  • Java Object類(lèi)詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java Object類(lèi)詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java作為一個(gè)龐大的知識(shí)體系,涉及到的知識(shí)點(diǎn)繁多,本文將從Java中最基本的類(lèi)java.lang.Object開(kāi)始談起,對(duì)java object類(lèi)相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2017-04-04
  • MyBatis Log Free插件IDE下載與使用方式

    MyBatis Log Free插件IDE下載與使用方式

    這篇文章主要介紹了MyBatis Log Free插件IDE下載與使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之二手書(shū)商城系統(tǒng)的實(shí)現(xiàn)

    Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之二手書(shū)商城系統(tǒng)的實(shí)現(xiàn)

    這是一個(gè)使用了java+JSP+Springboot+maven+mysql+ThymeLeaf+FTP開(kāi)發(fā)的二手書(shū)商城系統(tǒng),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有在線(xiàn)書(shū)城該有的所有功能,感興趣的朋友快來(lái)看看吧
    2022-01-01
  • SpringMVC和rabbitmq集成的使用案例

    SpringMVC和rabbitmq集成的使用案例

    這篇文章主要介紹了SpringMVC和rabbitmq集成的使用案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • Spring Boot中配置定時(shí)任務(wù)、線(xiàn)程池與多線(xiàn)程池執(zhí)行的方法

    Spring Boot中配置定時(shí)任務(wù)、線(xiàn)程池與多線(xiàn)程池執(zhí)行的方法

    這篇文章主要給大家介紹了關(guān)于Spring Boot中配置定時(shí)任務(wù)、線(xiàn)程池與多線(xiàn)程池執(zhí)行的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Shiro集成Spring之注解示例詳解

    Shiro集成Spring之注解示例詳解

    Shiro想必大家都知道了,是目前使用率要比spring security都要多的一個(gè)權(quán)限框架,下面這篇文章主要給大家介紹了關(guān)于Shiro集成Spring之注解的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-09-09
  • Java多線(xiàn)程ThreadPoolExecutor詳解

    Java多線(xiàn)程ThreadPoolExecutor詳解

    這篇文章主要介紹了Java多線(xiàn)程ThreadPoolExecutor詳解,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08

最新評(píng)論

新宁县| 安泽县| 吕梁市| 镇原县| 北宁市| 建瓯市| 海丰县| 通城县| 明溪县| 金华市| 翁牛特旗| 炎陵县| 浪卡子县| 丹凤县| 驻马店市| 穆棱市| 晋州市| 大姚县| 英山县| 九台市| 乌恰县| 洪湖市| 颍上县| 隆林| 藁城市| 云梦县| 行唐县| 西平县| 孙吴县| 察隅县| 庆安县| 麦盖提县| 青川县| 成安县| 民权县| 格尔木市| 开封县| 土默特右旗| 扶沟县| 彩票| 铁岭市|