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

Java利用多線程復(fù)制文件

 更新時(shí)間:2022年09月16日 09:46:55   作者:發(fā)光吖  
這篇文章主要介紹了Java利用多線程復(fù)制文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言

復(fù)制一個(gè)文件,是學(xué)習(xí)IO流時(shí)最基本的操作。你可以使用字節(jié)型文件流,也可以使用高級緩沖流。

但是,它們都是單線程的。

如果需要復(fù)制一個(gè)大型文件,單線程的復(fù)制一般而言是不能夠充分發(fā)揮CPU以及內(nèi)存的性能。這時(shí)候就需要利用多線程來復(fù)制文件。

多線程的讀:

我們很自然地想到,利用FileInputStream類的skip()方法,可以跳著讀,這就對多線程比較友好,啟動多個(gè)線程,第一個(gè)線程讀一部分,第二個(gè)線程跳過一部分字節(jié)再讀,這沒有問題。

但是如果要寫呢?我們知道FileOutputStream類是沒有與skip類似的方法的,也就是說,它不能跳著寫,這就很麻煩。

這就意味著,如果需要利用多線程復(fù)制一個(gè)文件,那么首先得把這個(gè)文件利用多線程并發(fā),讀取并同時(shí)寫入成多個(gè)文件碎片,然后再利用單線程去一一讀取這些文件碎片,把它們的內(nèi)容寫入到一個(gè)完整的文件中。必要的話,最后再刪除這些中間文件碎片。

這個(gè)過程,復(fù)雜,且性能不高。涉及到兩套讀寫,前面多線程讀寫,后面單線程讀寫。很顯然這個(gè)過程雖然使用到了多線程但它不能提高性能,反而降低了性能。

既然雞肋點(diǎn)在于FileOutputStream不能跳著寫,那么就找一個(gè)能跳著寫的類吧。

RandomAccessFile

RandomAccessFile是java Io體系中功能最豐富的文件內(nèi)容訪問類。即可以讀取文件內(nèi)容,也可以向文件中寫入內(nèi)容。但是和其他輸入/輸入流不同的是,程序可以直接跳到文件的任意位置來讀寫數(shù)據(jù)。

RandomAccessFile包含了以下兩個(gè)方法來操作文件的記錄指針:

  • long getFilePointer(); 返回文件記錄指針的當(dāng)前位置
  • void seek(long pos); 將文件記錄指針定位到pos位置

有了RandomAccessFile這個(gè)類,上面的問題就迎刃而解,因?yàn)樗畲蟮暮锰幘褪强梢詫?shí)現(xiàn)從指定位置寫入一些數(shù)據(jù)到文件中!

順便說一下它的構(gòu)造方法:

  • RandomAccessFile(File file, String mode)
  • RandomAccessFile(String name, String mode)

mode表示RandomAccessFile的訪問模式,她有4個(gè)值:

  • “r”:只有讀的權(quán)限,如果你試圖去執(zhí)行寫入方法,則拋出IOException異常。
  • “rw”:有讀和寫 兩個(gè)權(quán)限,如果該文件不存在,則會創(chuàng)建該文件。
  • “rws”:相對于”rw” 模式,還要求對文件內(nèi)容或元數(shù)據(jù)的每個(gè)更新都同步寫入到底層設(shè)備。
  • “rwd”:相對于”rw” 模式,還要求對文件內(nèi)容每個(gè)更新都同步寫入到底層設(shè)備。

一般而言我們使用“r”和“rw”就夠了,后面那兩個(gè)我也不懂干嘛的。

代碼

package testThread.file_threading;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;

public class ThreadFileCopy extends Thread {
? ? private String srcFileStr;//源文件的路徑
? ? private String desFileStr;//目標(biāo)文件的路徑 ,des --> destination目的地
? ? private long skipLen;//跳過多少個(gè)字節(jié)開始讀/寫
? ? private long workload;//總共要讀/寫多少個(gè)字節(jié)
? ? private final int IO_UNIT = 1024;//每次讀寫的基本單位(1024個(gè)字節(jié))

? ? public ThreadFileCopy(String srcFileStr, String desFileStr, long skipLen, long workload) {
? ? ? ? this.srcFileStr = srcFileStr;
? ? ? ? this.desFileStr = desFileStr;
? ? ? ? this.skipLen = skipLen;
? ? ? ? this.workload = workload;
? ? }
? ? public void run(){
? ? ? ? FileInputStream fis = null;
? ? ? ? BufferedInputStream bis = null;//利用高級緩沖流,加快讀的速度
? ? ? ? RandomAccessFile raf = null;
? ? ? ? try {
? ? ? ? ? ? fis = new FileInputStream(srcFileStr);
? ? ? ? ? ? bis = new BufferedInputStream(fis);
? ? ? ? ? ? raf = new RandomAccessFile(desFileStr,"rw");
? ? ? ? ? ? bis.skip(this.skipLen);//跳過一部分字節(jié)開始讀
? ? ? ? ? ? raf.seek(this.skipLen);//跳過一部分字節(jié)開始寫
? ? ? ? ? ? byte[] bytes = new byte[IO_UNIT];
? ? ? ? ? ? //根據(jù)總共需要復(fù)制的字節(jié)數(shù) 和 讀寫的基本單元 計(jì)算出一共需要讀寫的次數(shù),利用讀寫次數(shù)控制循環(huán)
? ? ? ? ? ? long io_num = this.workload/IO_UNIT + 1;//因?yàn)閣orkload/1024 很可能不能整除,會有余數(shù)
? ? ? ? ? ? if(this.workload % IO_UNIT == 0)
? ? ? ? ? ? ? ? io_num--;//如果碰巧整除,讀寫次數(shù)減一
? ? ? ? ? ? //count表示讀取的有效字節(jié)數(shù),雖然count不參與控制循環(huán)結(jié)束,
? ? ? ? ? ? // 但是它能有效避免最后一次讀取出的byte數(shù)組中有大量空字節(jié)寫入到文件中,導(dǎo)致復(fù)制出的文件稍稍變大
? ? ? ? ? ? int count = bis.read(bytes);
? ? ? ? ? ? while (io_num != 0){
? ? ? ? ? ? ? ? raf.write(bytes,0,count);
? ? ? ? ? ? ? ? count = bis.read(bytes,0,count);//重新計(jì)算count的值
? ? ? ? ? ? ? ? io_num--;
? ? ? ? ? ? }
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }finally {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? if (fis != null)
? ? ? ? ? ? ? ? ? ? fis.close();
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? if (bis != null)
? ? ? ? ? ? ? ? ? ? bis.close();
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? if (raf != null)
? ? ? ? ? ? ? ? ? ? raf.close();
? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
}

測試

package testThread.file_threading;

import java.io.File;

public class TestMain {
? ? public static void main(String[] args) {
? ? ? ? int thread_num = 5;//創(chuàng)建5個(gè)線程讀寫
? ? ? ? String srcFileStr = "E:\\test\\123.flv";
? ? ? ? String desFileStr = "E:\\test\\thread.flv";
? ? ? ? File srcFile = new File(srcFileStr);
? ? ? ? long workload = srcFile.length()/thread_num;//總共要讀/寫多少個(gè)字節(jié)
? ? ? ? //用一個(gè)數(shù)組來存儲每個(gè)線程跳過的字節(jié)數(shù)
? ? ? ? long[] skipLenArr = new long[thread_num];
? ? ? ? for(int i = 0;i<skipLenArr.length;i++){
? ? ? ? ? ? skipLenArr[i] = i*workload;
? ? ? ? }
? ? ? ? //用一個(gè)數(shù)組來存儲所有的線程
? ? ? ? ThreadFileCopy[] tfcs = new ThreadFileCopy[thread_num];
? ? ? ? //初始化所有線程
? ? ? ? for(int i = 0;i<tfcs.length;i++){
? ? ? ? ? ? tfcs[i] = new ThreadFileCopy(srcFileStr,desFileStr,skipLenArr[i],workload);
? ? ? ? }
? ? ? ? //讓所有線程進(jìn)入就緒狀態(tài)
? ? ? ? for(int i = 0;i<tfcs.length;i++){
? ? ? ? ? ? tfcs[i].start();
? ? ? ? }
? ? ? ? System.out.println("復(fù)制完畢!");
? ? }
}

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

相關(guān)文章

  • SpringBoot整合Redis之編寫RedisConfig

    SpringBoot整合Redis之編寫RedisConfig

    RedisConfig需要對redis提供的兩個(gè)Template的序列化配置,所以本文為大家詳細(xì)介紹了SpringBoot整合Redis如何編寫RedisConfig,需要的可以參考下
    2022-06-06
  • Java的面向?qū)ο缶幊袒靖拍顚W(xué)習(xí)筆記整理

    Java的面向?qū)ο缶幊袒靖拍顚W(xué)習(xí)筆記整理

    這篇文章主要介紹了Java的面向?qū)ο缶幊袒靖拍顚W(xué)習(xí)筆記整理,包括類與方法以及多態(tài)等支持面向?qū)ο笳Z言中的重要特點(diǎn),需要的朋友可以參考下
    2016-01-01
  • 利用Java搭建個(gè)簡單的Netty通信實(shí)例教程

    利用Java搭建個(gè)簡單的Netty通信實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于如何利用Java搭建個(gè)簡單的Netty通信,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Java實(shí)現(xiàn)ftp上傳下載、刪除文件及在ftp服務(wù)器上傳文件夾的方法

    Java實(shí)現(xiàn)ftp上傳下載、刪除文件及在ftp服務(wù)器上傳文件夾的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)ftp上傳下載、刪除文件及在ftp服務(wù)器上傳文件夾的方法,需要的朋友可以參考下
    2015-11-11
  • RocketMQ中的消費(fèi)者啟動流程解讀

    RocketMQ中的消費(fèi)者啟動流程解讀

    這篇文章主要介紹了RocketMQ中的消費(fèi)者啟動流程解讀,RocketMQ是一款高性能、高可靠性的分布式消息中間件,消費(fèi)者是RocketMQ中的重要組成部分,消費(fèi)者負(fù)責(zé)從消息隊(duì)列中獲取消息并進(jìn)行處理,需要的朋友可以參考下
    2023-10-10
  • Spring Boot 參數(shù)校驗(yàn)的具體實(shí)現(xiàn)方式

    Spring Boot 參數(shù)校驗(yàn)的具體實(shí)現(xiàn)方式

    這篇文章主要介紹了Spring Boot 參數(shù)校驗(yàn)的具體實(shí)現(xiàn)方式,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-06-06
  • SpringBoot快速整合RabbitMq小案例(使用步驟)

    SpringBoot快速整合RabbitMq小案例(使用步驟)

    這篇文章主要介紹了SpringBoot快速整合RabbitMq小案例,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Java eclipse doc文檔生成流程解析

    Java eclipse doc文檔生成流程解析

    這篇文章主要介紹了Java eclipse doc文檔生成流程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • 使用Mybatis實(shí)現(xiàn)分頁效果示例

    使用Mybatis實(shí)現(xiàn)分頁效果示例

    大家好,本篇文章主要講的是使用Mybatis實(shí)現(xiàn)分頁效果示例,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決

    解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決

    這篇文章主要介紹了解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評論

潼南县| 揭东县| 胶州市| 怀集县| 五台县| 双柏县| 县级市| 咸阳市| 兴安县| 溧阳市| 奉新县| 禹州市| 湘潭市| 平昌县| 清河县| 通许县| 宣恩县| 从江县| 墨脱县| 和林格尔县| 阿拉善左旗| 临猗县| 讷河市| 文安县| 房山区| 正蓝旗| 曲阳县| 中宁县| 灵武市| 鄂温| 日喀则市| 岑巩县| 漳浦县| 辽宁省| 潼关县| 黄石市| 大连市| 陇西县| 望奎县| 昔阳县| 筠连县|