精华内容
下载资源
问答
  • 多线程实现多文件下载java
    千次阅读
    2022-04-03 23:59:34

     这是本人在实际开发当中遇到的多线程下载文件并记录下来

    public class DownloadUtil {
        private String pathFile;
        private String strFile;
        private DownloadThread[] downloadThreadArr;
        private int threadNum;
        private int size;
    
        public DownloadUtil (String pathFile, String strFile, int threadNum) {
            this.pathFile = pathFile;
            this.threadNum = threadNum;
            downloadThreadArr = new DownloadThread[threadNum];
            this.strFile = strFile;
        }
    
        public void download() throws Exception {
            URL url = new URL(pathFile);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod("GET");
            conn.setRequestProperty(
                    "Accept",
                    "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
                            + "application/x-shockwave-flash, application/xaml+xml, "
                            + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
                            + "application/x-ms-application, application/vnd.ms-excel, "
                            + "application/vnd.ms-powerpoint, application/msword, */*");
            conn.setRequestProperty("Accept-Language", "zh-CN");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("Connection", "Keep-Alive");
    
            size = conn.getContentLength();
            conn.disconnect();
            int currentPartSize = size / threadNum + 1;
            RandomAccessFile file = new RandomAccessFile(strFile, "rw");
            file.setLength(size);
            file.close();
            for (int i = 0; i < threadNum; i++) {
                int start = i * currentPartSize;
                RandomAccessFile currentPart = new RandomAccessFile(strFile, "rw");
                currentPart.seek(start);
                downloadThreadArr[i] = new DownloadThread(start, currentPartSize, currentPart);
                downloadThreadArr[i].start();
            }
        }
    
        
        class DownloadThread extends Thread {
            private int start;
            private int size;
            private RandomAccessFile out;
            public int length;
            
            public DownloadThread(int start, int size,RandomAccessFile out) {
                this.out = out;
                this.start = start;
                this.size = size;
            }
    
            @Override
            public void run() {
                InputStream is = null;
                try {
                    URL url = new URL(pathFile);
                    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setRequestMethod("GET");
                    conn.setRequestProperty(
                            "Accept",
                            "image/gif, image/jpeg, image/pjpeg, image/pjpeg, " + "application/x-shockwave-flash, application/xaml+xml, " + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
                                    + "application/x-ms-application, application/vnd.ms-excel, "
                                    + "application/vnd.ms-powerpoint, application/msword, */*");
                    conn.setRequestProperty("Accept-Language", "zh-CN");
                    conn.setRequestProperty("Charset", "UTF-8");
                    is = conn.getInputStream();
                    is.skip(this.start);
                    byte[] bs = new byte[1024];
                    int len = 0;
                    while ((len = is.read(bs)) != -1 && length < size) {
                        out.write(bs, 0, len);
                        length += len;
                    }
                    out.close();
                    is.close();
                }
                catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    try {
                        out.close();
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                   
                }
            }
        }
    
       
    }
    
    
    
    
    
    
    
    @RestController
    @RequestMapping("tc")
    public class TestController {
    
        @RequestMapping("/download")
        public void download(String filePath,String savePath) {
            try {
                DownloadUtil downloadUtil = new DownloadUtil (filePath,savePath,10);
                downloadUtil.download();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    更多相关内容
  • 主要介绍了java多线程实现文件下载功能的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要为大家详细介绍了java多线程实现文件下载,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了Java多线程文件分片下载实现的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 利用java技术实现多线程文件传输
  • 主要介绍了Java多线程下载文件实现案例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了使用java的HttpClient实现多线程并发的相关资料,需要的朋友可以参考下
  • 本篇文章主要介绍了Java实现多线程下载的代码示例,Java多线程可以充分利用CPU的资源,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
  • 线程可以理解为下载的通道,一个线程就是一个文件下载通道,多线程也就是同时开启好几个下载通道,Java实现多线程断点下载实例代码(下载过程中可以暂停),有兴趣的可以了解一下。
  • JAVA 实现多线程下载文件

    千次阅读 2021-12-28 15:22:09
    JAVA 实现多线程下载文件 开发中遇到一个问题,下载文件到本地,导致等待时间过长,然后就寻找一个可以多线程下载的办法,受下载软件启发,想到多线程下载, 原理,首先查到这个文件的大小,然后根据线程数量...

    JAVA 实现多线程下载大文件

    开发中遇到一个问题,下载大文件到本地,导致等待时间过长,然后就寻找一个可以多线程下载的办法,受下载软件启发,想到多线程下载,
    原理,首先查到这个文件的大小,然后根据线程数量去分配每个线程下载多大的片段,然后将每个线程的组合到一起,就是最终的下载文件。如图

    在这里插入图片描述

    然后就是代码时间, 必不可少的控制层

        @Override
        @ApiOperation(value = "多线程获取大文件", httpMethod = "POST")
        @BodyValidate
        public Result getBigFile(@RequestBody CommonFileRequest commonFileRequest, HttpServletResponse response) {
            return commonFileService.getBigFile(commonFileRequest,response);
        }
    

    然后是业务层

     /**
         * .
         * @Description: 作用:   多线程获取大文件
         * @Author: LXT
         * @Date: 2021/12/27 9:18
         * @param request 入参
         * @return Result
         */
        public Result getBigFile(CommonFileRequest request, HttpServletResponse response) {
            logger.info("多线程获取大文件," + JSON.toJSONString(request));
             long start = System.currentTimeMillis();
            //超大  6G
            //String path = "???";
            // 1.3G
            //String path = "???";
            //正常大小
            String path = "???";
    
            try {
                ServletOutputStream out = null;
    
                String s = BigFileDownload.BigFileTestUtil(accessKey, secretKey, endpoint, bucketName, path);
                File file = new File(s);
                InputStream fis = new BufferedInputStream(new FileInputStream(file));
    
                response.reset();
                // 设置response的Header
                response.addHeader("Content-Length", "" + file.length());
                response.setContentType("application/octet-stream;charset=UTF-8");
                response.setHeader("Content-disposition", "attachment;filename=" + UUID.randomUUID().toString().replace("-", "") + ".zip");
    
                out = response.getOutputStream();
                //读取文件流
                int len = 0;
                byte[] buffer = new byte[1024 * 10];
                while ((len = fis.read(buffer)) != -1){
                    out.write(buffer,0,len);
                }
                out.flush();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            logger.info("获取大文件耗时 {}", BusinessStringUtils.formatTime(System.currentTimeMillis() - start));
    
            return null;
        }
    

    解析 首先 记录一下请求的日志 然后是拿到对应的存储位置
    然后去平台获取文件 BigFileDownload.BigFileTestUtil 这个方法
    返回的缓存在服务器 或者本地的一个位置 然后将其返回给移动端
    后边这些就不说了 都是正常的反流代码 这里着重说明 多线程分片下载

    
    /**
     * .
     *
     * @ClassName: BigFileDownload
     * @Description:
     * @Author: LXT
     * @Date: 2021/12/27 13:01
     */
    public class BigFileDownload {
    
        //创建一个计数器锁。初始值为线程数量,每执行结束一个线程后计数器减去1 ,当计数器为0的时候await等待的线程会被唤醒继续执行。
        public static CountDownLatch latch = new CountDownLatch(100);
    
    
        public static String BigFileTestUtil(String accessKey, String secretKey, String endpoint, String bucketName, String downloadFilePath) {
            RandomAccessFile file = null;
            String filename = "D:\\222ddddd2.zip";
            File fileDownService = new File(filename);
            if (!fileDownService.exists()) {
                try {
                    fileDownService.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println("文件已创建");
            } else {
                System.out.println("文件已存在");
            }
            try {
                AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
                ClientConfiguration clientConfig = new ClientConfiguration();
                clientConfig.setProtocol(Protocol.HTTP);
                AmazonS3 s3Client = new AmazonS3Client(credentials, clientConfig);
                s3Client.setEndpoint(endpoint);
                //获取对象大小
                AmazonS3 instance = AmazonS3Builder.getInstance(endpoint, accessKey, secretKey);
                S3Object object = instance.getObject(bucketName, downloadFilePath);
                S3ObjectInputStream in3 = object.getObjectContent();
                ObjectMetadata metadata = object.getObjectMetadata();
                long filesize = metadata.getInstanceLength();
                System.out.println("文件大小:" + filesize);
    
                ExecutorService service = Executors.newFixedThreadPool(100);
                long length = filesize;
                long packageLength = length / 100;
                long leftLength = length % 100;
                long pos = 0;
                long end = packageLength;
                file = new RandomAccessFile(filename, "rw");
                //计算每个线程请求文件的开始和结束位置
                for (int i = 0; i < 100; i++) {
                    if (leftLength > 0) {
                        packageLength++;
                        leftLength--;
                    }
                    System.out.println("pos: " + pos + "  endpos: " + packageLength);
                    service.execute(new BigFileDownloadRunnable(pos, packageLength, file, endpoint, accessKey, secretKey, bucketName, downloadFilePath));
                    pos = packageLength;
                    packageLength = packageLength + end;
                }
                //等待其他线程结束后继续向下执行
                try {
                    latch.await();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                //关闭线程池
                service.shutdown();
            } catch (AmazonServiceException | FileNotFoundException e) {
                // 服务端错误
                e.printStackTrace();
            } finally {
                if (file != null) {
                    try {
                        file.close();
                    } catch (Exception e) {
    
                    }
                }
            }
            return filename;
    
        }
    
    }
    

    其实也比较好理解 首先创建一个线程 用来分片下载
    然后是主代码
    方法入参 分别是 对象平台的一些参数 只有随后一个是存储平台地址 其他平台可自行更改
    然后就是做一个本地缓存用的假文件
    接着到 异常里
    先做存储平台的链接,然后获取要下载文件的大小
    获取大小后 更具线程数量 自行计算启动多少个线程来下载 我这里直接给的100 然后使用for进行线程的启动 启动后进入线程等待 全执行完之后 可正常生成文件,

    然后就是线程使用的分片下载工具类

    
    /**
     * .
     *
     * @ClassName: BigFileDownloadRunnable
     * @Description:
     * @Author: LXT
     * @Date: 2021/12/27 13:19
     */
    
    class BigFileDownloadRunnable implements Runnable {
    
        private String endpoint;
    
        private String accessKey;
    
        private String secretKey;
    
        private String bucketName;
    
        private long from;
    
        private long end;
    
        private RandomAccessFile file;
    
        private String downloadFilePath;
    
        public BigFileDownloadRunnable(long from, long end, RandomAccessFile file,
                                       String endpoint, String accessKey, String secretKey, String bucketName,String downloadFilePath) {
            this.from = from;
            this.end = end;
            this.file = file;
            this.endpoint = endpoint;
            this.accessKey = accessKey;
            this.secretKey = secretKey;
            this.bucketName = bucketName;
            this.downloadFilePath = downloadFilePath;
        }
    
        public void run() {
    
            String filename = downloadFilePath;
            S3Object objectPortion = null;
            InputStream input = null;
            BufferedInputStream buffer = null;
            try {
                AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
                ClientConfiguration clientConfig = new ClientConfiguration();
                clientConfig.setProtocol(Protocol.HTTP);
                clientConfig.setConnectionTimeout(90000000);
                clientConfig.setMaxConnections(1000);
                AmazonS3 s3Client = new AmazonS3Client(credentials, clientConfig);
                s3Client.setEndpoint(endpoint);
                //获取对象指定范围的流写入文件
                GetObjectRequest rangeObjectRequest = new GetObjectRequest(bucketName, filename).withRange(from, end);
                objectPortion = s3Client.getObject(rangeObjectRequest);
    
                input = objectPortion.getObjectContent();
                buffer = new BufferedInputStream(input);
    
                byte[] buf = new byte[1024];
                int len;
                long start = this.from;
                long stop = this.end;
                for (; ; ) {
                    if ((len = buffer.read(buf)) == -1) {
                        break;
                    }
                    synchronized (file) {
                        file.seek(from);
                        file.write(buf, 0, len);
                    }
                    from += len;
                }
                System.out.println("文件片段 " + start + "~" + stop + "下载完成");
                new BigFileDownload().latch.countDown();//线程结束计数器减1
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                if (buffer != null) {
                    try {
                        buffer.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if (objectPortion != null) {
                    try {
                        objectPortion.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    

    因为线程分段 也需要去请球平台 所以就将平台的数据一并传输过来

    然后线程内run 大概意思 就是 我拿到了平台链接 然后又有文件的存错位置 还有我需要下载的片段位置,然后就是正常下载过程

    由于大文件比较大 链接时间设置的相对较长一点,

    一小点的进步都是对开发者的激励,记录一下,分享给大家。有用记得点♥

    展开全文
  • 针对操作系统中多线程部分知识开发的一个案例,有助于更好的理解线程
  • NULL 博文链接:https://zhouyq.iteye.com/blog/271778
  • java实现多线程下载文件功能,通过线程池管理,实现下载文件速度快,安全。
  • java多线程下载文件

    2022-07-14 14:41:52
    使用java实现文件下载 单线程提示进度 多线程下载文件
  • Android 文件下载功能Java多线程下载功能的例子实例源码
  • 复习多线程的时候,练习了下,顺便记录一下:
  • 多线程下载文件平时开发中有时会用到文件下载,为了提高文件的下载速率,采用多线程下载能够达到事半功倍的效果:packagetest;/***文件下载类* @author luweicheng**/import java.io.FileInputStream;import java.io...

    多线程下载文件

    平时开发中有时会用到文件下载,为了提高文件的下载速率,采用多线程下载能够达到事半功倍的效果:

    packagetest;

    /**

    *文件下载类

    * @author luweicheng

    *

    */

    import java.io.FileInputStream;

    import java.io.FileNotFoundException;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.RandomAccessFile;

    import java.net.HttpURLConnection;

    import java.net.URL;

    import java.net.URLConnection;

    public class DownFile{

    private URLfileUrl;//文件下载路径

    private intthreadCount;//文件下载的线程数

    private intstartPos;//每个线程下载文件的开始位置

    private intsize;//每个线程下载文件的长度

    private intfileLength;//文件总程度

    private StringpathName;//下载的文件路径(包含文件名)

    private Downthread[] tDownthreads;//线程数组

    public DownFile(URLurl,intthreadCount,StringpathName)throws IOException{

    fileUrl=url;

    this.threadCount=threadCount;

    this.pathName=pathName;

    init();

    }

    /**

    *初始化

    *

    * @throws IOException

    */

    private void init()throws IOException{

    tDownthreads= new Downthread[threadCount];

    HttpURLConnectionconn=(HttpURLConnection) fileUrl.openConnection();

    conn.setConnectTimeout(5000);

    conn.setRequestMethod("GET");

    conn.setRequestProperty("connection","keep-alive");

    fileLength=conn.getContentLength();

    System.out.println("文件长度" +fileLength);

    size=fileLength/threadCount;

    System.out.println("每个下载量==" +size);

    conn.disconnect();//断开链接

    }

    public URL getFileUrl() {

    returnfileUrl;

    }

    public int getThreadCount() {

    return this.threadCount;

    }

    /**

    *开始下载

    */

    public void startDown() {

    for(inti= 0; i

    try{

    RandomAccessFileraFile= new RandomAccessFile(pathName,"rw");

    tDownthreads[i]= new Downthread(i*size, raFile, i);

    tDownthreads[i].start();

    }catch(FileNotFoundExceptione) {

    e.printStackTrace();

    }

    }

    }

    /**

    *下载线程类

    *

    * @author luweicheng

    *

    */

    class Downthread extends Thread{

    private intstartPos;//开始的位置

    private InputStreamis;

    private RandomAccessFileraFile;

    private intlength;//下载的文件长度

    private intflag;//线程标志

    public Downthread(intstartPos,RandomAccessFileraFile,inti) {

    this.startPos=startPos;

    this.raFile=raFile;

    flag=i;

    }

    @Override

    public void run() {

    try{

    HttpURLConnectionconnection=(HttpURLConnection) fileUrl.openConnection();

    connection.setRequestMethod("GET");

    connection.setRequestProperty("connection","keep-alive");

    connection.setConnectTimeout(5 * 1000);

    is=connection.getInputStream();

    is.skip(startPos);

    raFile.seek(startPos);

    byte[] buf= new byte[8 * 1024];

    inthasread= 0;//读出的字节数

    //将位置在 startPos - startPos 位置的数据读出写入

    while(length

    raFile.write(buf,0, hasread);

    length+=hasread;

    System.out.println("*****线程" +flag+ "下载了*********" +length);

    }

    System.out.println("*******线程" +flag+ "下载完成*********");

    }catch(IOExceptione) {

    }finally{

    try{

    is.close();

    raFile.close();

    }catch(IOExceptione) {

    e.printStackTrace();

    }

    }

    }

    }

    }

    效果展示:

    170ef61dcee5dd92d8f30b8cefb5b67d.png

    详细配置信息可以参考这篇文章:

    展开全文
  • 使用java socket开发的多线程文件上传下载的实例项目,多线程并发测试中可以支持200个,可能由于我电脑的配置问题,一般在并发大于200时client端可能会出现"阻塞"问题,还请大家指教
  • 在读取超过10G的文件时会发现一次读一行的速度实在是不能接受,想到使用多线程+FileChannel来做一个使用多线程版本。基本思路如下:1.计算出文件总大小2.分段处理,计算出每个线程读取文件的开始与结束位置(文件大小/...

    接上次写的“JAVA读取超大文件”。在读取超过10G的文件时会发现一次读一行的速度实在是不能接受,想到使用多线程+FileChannel来做一个使用多线程版本。

    基本思路如下:

    1.计算出文件总大小

    2.分段处理,计算出每个线程读取文件的开始与结束位置

    (文件大小/线程数)*N,N是指第几个线程,这样能得到每个线程在读该文件的大概起始位置

    使用"大概起始位置",作为读文件的开始偏移量(fileChannel.position("大概起始位置")),来读取该文件,直到读到第一个换行符,记录下这个换行符的位置,作为该线程的准确起 始位置.同时它也是上一个线程的结束位置.最后一个线程的结束位置也直接设置为-1

    3.启动线程,每个线程从开始位置读取到结束位置为止

    代码如下:

    读文件工具类

    import java.io.*;

    import java.nio.ByteBuffer;

    import java.nio.channels.FileChannel;

    import java.util.Observable;

    /**

    * Created with IntelliJ IDEA.

    * User: okey

    * Date: 14-4-2

    * Time: 下午3:12

    * 读取文件

    */

    public class ReadFile extends Observable {

    private int bufSize = 1024;

    // 换行符

    private byte key = "\n".getBytes()[0];

    // 当前行数

    private long lineNum = 0;

    // 文件编码,默认为gb2312

    private String encode = "gb2312";

    // 具体业务逻辑监听器

    private ReaderFileListener readerListener;

    public void setEncode(String encode) {

    this.encode = encode;

    }

    public void setReaderListener(ReaderFileListener readerListener) {

    this.readerListener = readerListener;

    }

    /**

    * 获取准确开始位置

    * @param file

    * @param position

    * @return

    * @throws Exception

    */

    public long getStartNum(File file, long position) throws Exception {

    long startNum = position;

    FileChannel fcin = new RandomAccessFile(file, "r").getChannel();

    fcin.position(position);

    try {

    int cache = 1024;

    ByteBuffer rBuffer = ByteBuffer.allocate(cache);

    // 每次读取的内容

    byte[] bs = new byte[cache];

    // 缓存

    byte[] tempBs = new byte[0];

    String line = "";

    while (fcin.read(rBuffer) != -1) {

    int rSize = rBuffer.position();

    rBuffer.rewind();

    rBuffer.get(bs);

    rBuffer.clear();

    byte[] newStrByte = bs;

    // 如果发现有上次未读完的缓存,则将它加到当前读取的内容前面

    if (null != tempBs) {

    int tL = tempBs.length;

    newStrByte = new byte[rSize + tL];

    System.arraycopy(tempBs, 0, newStrByte, 0, tL);

    System.arraycopy(bs, 0, newStrByte, tL, rSize);

    }

    // 获取开始位置之后的第一个换行符

    int endIndex = indexOf(newStrByte, 0);

    if (endIndex != -1) {

    return startNum + endIndex;

    }

    tempBs = substring(newStrByte, 0, newStrByte.length);

    startNum += 1024;

    }

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    fcin.close();

    }

    return position;

    }

    /**

    * 从设置的开始位置读取文件,一直到结束为止。如果 end设置为负数,刚读取到文件末尾

    * @param fullPath

    * @param start

    * @param end

    * @throws Exception

    */

    public void readFileByLine(String fullPath, long start, long end) throws Exception {

    File fin = new File(fullPath);

    if (fin.exists()) {

    FileChannel fcin = new RandomAccessFile(fin, "r").getChannel();

    fcin.position(start);

    try {

    ByteBuffer rBuffer = ByteBuffer.allocate(bufSize);

    // 每次读取的内容

    byte[] bs = new byte[bufSize];

    // 缓存

    byte[] tempBs = new byte[0];

    String line = "";

    // 当前读取文件位置

    long nowCur = start;

    while (fcin.read(rBuffer) != -1) {

    nowCur += bufSize;

    int rSize = rBuffer.position();

    rBuffer.rewind();

    rBuffer.get(bs);

    rBuffer.clear();

    byte[] newStrByte = bs;

    // 如果发现有上次未读完的缓存,则将它加到当前读取的内容前面

    if (null != tempBs) {

    int tL = tempBs.length;

    newStrByte = new byte[rSize + tL];

    System.arraycopy(tempBs, 0, newStrByte, 0, tL);

    System.arraycopy(bs, 0, newStrByte, tL, rSize);

    }

    // 是否已经读到最后一位

    boolean isEnd = false;

    // 如果当前读取的位数已经比设置的结束位置大的时候,将读取的内容截取到设置的结束位置

    if (end > 0 && nowCur > end) {

    // 缓存长度 - 当前已经读取位数 - 最后位数

    int l = newStrByte.length - (int) (nowCur - end);

    newStrByte = substring(newStrByte, 0, l);

    isEnd = true;

    }

    int fromIndex = 0;

    int endIndex = 0;

    // 每次读一行内容,以 key(默认为\n) 作为结束符

    while ((endIndex = indexOf(newStrByte, fromIndex)) != -1) {

    byte[] bLine = substring(newStrByte, fromIndex, endIndex);

    line = new String(bLine, 0, bLine.length, encode);

    lineNum++;

    // 输出一行内容,处理方式由调用方提供

    readerListener.outLine(line.trim(), lineNum, false);

    fromIndex = endIndex + 1;

    }

    // 将未读取完成的内容放到缓存中

    tempBs = substring(newStrByte, fromIndex, newStrByte.length);

    if (isEnd) {

    break;

    }

    }

    // 将剩下的最后内容作为一行,输出,并指明这是最后一行

    String lineStr = new String(tempBs, 0, tempBs.length, encode);

    readerListener.outLine(lineStr.trim(), lineNum, true);

    } catch (Exception e) {

    e.printStackTrace();

    } finally {

    fcin.close();

    }

    } else {

    throw new FileNotFoundException("没有找到文件:" + fullPath);

    }

    // 通知观察者,当前工作已经完成

    setChanged();

    notifyObservers(start+"-"+end);

    }

    /**

    * 查找一个byte[]从指定位置之后的一个换行符位置

    *

    * @param src

    * @param fromIndex

    * @return

    * @throws Exception

    */

    private int indexOf(byte[] src, int fromIndex) throws Exception {

    for (int i = fromIndex; i < src.length; i++) {

    if (src[i] == key) {

    return i;

    }

    }

    return -1;

    }

    /**

    * 从指定开始位置读取一个byte[]直到指定结束位置为止生成一个全新的byte[]

    *

    * @param src

    * @param fromIndex

    * @param endIndex

    * @return

    * @throws Exception

    */

    private byte[] substring(byte[] src, int fromIndex, int endIndex) throws Exception {

    int size = endIndex - fromIndex;

    byte[] ret = new byte[size];

    System.arraycopy(src, fromIndex, ret, 0, size);

    return ret;

    }

    }

    读文件线程

    /**

    * Created with IntelliJ IDEA.

    * User: okey

    * Date: 14-4-2

    * Time: 下午4:50

    * To change this template use File | Settings | File Templates.

    */

    public class ReadFileThread extends Thread {

    private ReaderFileListener processPoiDataListeners;

    private String filePath;

    private long start;

    private long end;

    public ReadFileThread(ReaderFileListener processPoiDataListeners,long start,long end,String file) {

    this.setName(this.getName()+"-ReadFileThread");

    this.start = start;

    this.end = end;

    this.filePath = file;

    this.processPoiDataListeners = processPoiDataListeners;

    }

    @Override

    public void run() {

    ReadFile readFile = new ReadFile();

    readFile.setReaderListener(processPoiDataListeners);

    readFile.setEncode(processPoiDataListeners.getEncode());

    // readFile.addObserver();

    try {

    readFile.readFileByLine(filePath, start, end + 1);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    具体业务逻辑监听

    /**

    * Created with Okey

    * User: Okey

    * Date: 13-3-14

    * Time: 下午3:19

    * NIO逐行读数据回调方法

    */

    public abstract class ReaderFileListener {

    // 一次读取行数,默认为500

    private int readColNum = 500;

    private String encode;

    private List list = new ArrayList();

    /**

    * 设置一次读取行数

    * @param readColNum

    */

    protected void setReadColNum(int readColNum) {

    this.readColNum = readColNum;

    }

    public String getEncode() {

    return encode;

    }

    public void setEncode(String encode) {

    this.encode = encode;

    }

    /**

    * 每读取到一行数据,添加到缓存中

    * @param lineStr 读取到的数据

    * @param lineNum 行号

    * @param over 是否读取完成

    * @throws Exception

    */

    public void outLine(String lineStr, long lineNum, boolean over) throws Exception {

    if(null != lineStr)

    list.add(lineStr);

    if (!over && (lineNum % readColNum == 0)) {

    output(list);

    list.clear();

    } else if (over) {

    output(list);

    list.clear();

    }

    }

    /**

    * 批量输出

    *

    * @param stringList

    * @throws Exception

    */

    public abstract void output(List stringList) throws Exception;

    }

    线程调度

    import java.io.File;

    import java.io.FileInputStream;

    import java.io.IOException;

    /**

    * Created with IntelliJ IDEA.

    * User: okey

    * Date: 14-4-1

    * Time: 下午6:03

    * To change this template use File | Settings | File Templates.

    */

    public class BuildData {

    public static void main(String[] args) throws Exception {

    File file = new File("E:\\1396341974289.csv");

    FileInputStream fis = null;

    try {

    ReadFile readFile = new ReadFile();

    fis = new FileInputStream(file);

    int available = fis.available();

    int maxThreadNum = 50;

    // 线程粗略开始位置

    int i = available / maxThreadNum;

    for (int j = 0; j < maxThreadNum; j++) {

    // 计算精确开始位置

    long startNum = j == 0 ? 0 : readFile.getStartNum(file, i * j);

    long endNum = j + 1 < maxThreadNum ? readFile.getStartNum(file, i * (j + 1)) : -2;

    // 具体监听实现

    ProcessDataByPostgisListeners listeners = new ProcessDataByPostgisListeners("gbk");

    new ReadFileThread(listeners, startNum, endNum, file.getPath()).start();

    }

    } catch (IOException e) {

    e.printStackTrace();

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    现在就可以尽情的调整 maxThreadNum来享受风一般的速度吧!

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

    时间: 2019-08-28

    展开全文
  • 主要介绍了Android实现网络多线程文件下载的相关资料,需要的朋友可以参考下
  • 主要为大家详细介绍了Java实现多线程断点下载的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 多线程下载文件是很实用的加速技巧,今天介绍多线程下载文件 前文回顾 【Java 两种简单的方式实现多线程】 【Java ExecutorService管理线程池的简单用法】 【JAVA URLConnection 实现下载文件】 单一线程下载文件...
  • JAVA实现文件多线程下载,提速30倍! 前言 兄弟们看到这个标题可能会觉得是个标题党,为了解决疑虑,我们先来看下最终的测试结果: 测试云盘下载文件 46M,自己本地最大下载速度 2M 1. 单线程下载,总耗时: 603s...
  • 轻松解决普通poi形式导出Excel的中出现的栈溢出问题,此资源可实现千万级数据分批导出csv文件,csv大数据量导出(千万级别,不会内存溢出),多线程导出 ,生产环境已经很稳定的使用着
  • 用开源 Apache POI 技术导出Excel,解决导出大数据出现OOM、栈溢出问题,此资源可实现百万级数据多线程分批导出Excel文件,不会内存溢出,生产环境已很稳定的使用者,所以用到的技术很核心、值得参考
  • 使用多线程实现多个文件同步复制功能,并在控制台显示复制的进度,进度以百分比表示。 1.创建一个普通类,实现runnable中的run方法 package com.yc123.model; import java.io.File; import java.io.FileInputStream;...
  • java的ftp多线程下载

    热门讨论 2014-10-02 20:42:47
    本程序是在原有基础上逐步完善的,第一:http://download.csdn.net/detail/zpwmhx/4342943 第二:http://download.csdn.net/detail/zpwmhx/4505209 ...本程序很适合在主机间批量传输文件和目录,参数可控
  • 2、支持多任务多线程同时下载; 3、每个任务的线程数由用户在新建任务时自定义,缺省为5个线程; 4、任务下载过程中可以点击“线程+”或“线程-”即时增减线程; 5、选择任务,可以在任务信息栏中查看任务下载的信息...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 328,813
精华内容 131,525
关键字:

多线程实现多文件下载java

友情链接: MAX4051.rar