-
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多线程实现文件下载功能
2020-08-31 15:26:17主要介绍了java多线程实现文件下载功能的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
java多线程实现文件下载
2020-08-25 19:53:14主要为大家详细介绍了java多线程实现文件下载,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
Java多线程文件分片下载实现的示例代码
2020-08-24 22:36:26主要介绍了Java多线程文件分片下载实现的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 -
java实现多线程文件传输
2016-03-22 16:33:24利用java技术实现多线程文件传输 -
Java多线程下载文件实现案例详解
2020-08-19 04:34:31主要介绍了Java多线程下载文件实现案例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 -
使用java的HttpClient实现多线程并发
2020-09-01 15:52:23主要介绍了使用java的HttpClient实现多线程并发的相关资料,需要的朋友可以参考下 -
Java实现多线程文件下载的代码示例
2020-08-31 07:35:05本篇文章主要介绍了Java实现多线程下载的代码示例,Java多线程可以充分利用CPU的资源,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。 -
Java实现多线程断点下载实例代码(下载过程中可以暂停)
2020-08-31 21:47:26线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道,Java实现多线程断点下载实例代码(下载过程中可以暂停),有兴趣的可以了解一下。 -
JAVA 实现多线程下载大文件
2021-12-28 15:22:09JAVA 实现多线程下载大文件 开发中遇到一个问题,下载大文件到本地,导致等待时间过长,然后就寻找一个可以多线程下载的办法,受下载软件启发,想到多线程下载, 原理,首先查到这个文件的大小,然后根据线程数量...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 大概意思 就是 我拿到了平台链接 然后又有文件的存错位置 还有我需要下载的片段位置,然后就是正常下载过程
由于大文件比较大 链接时间设置的相对较长一点,
一小点的进步都是对开发者的激励,记录一下,分享给大家。有用记得点♥
-
Java实现文件的多线程下载
2018-12-21 19:01:45针对操作系统中多线程部分知识开发的一个案例,有助于更好的理解线程 -
使用java实现http多线程下载
2019-03-01 17:07:33NULL 博文链接:https://zhouyq.iteye.com/blog/271778 -
java实现多线程下载文件
2009-12-17 16:14:07java实现多线程下载文件功能,通过线程池管理,实现下载文件速度快,安全。 -
java多线程下载文件
2022-07-14 14:41:52使用java实现文件下载 单线程提示进度 多线程下载文件 -
Android 文件下载功能Java多线程下载功能的例子实例源码.zip
2022-05-14 14:33:06Android 文件下载功能Java多线程下载功能的例子实例源码 -
Java多线程下载的实现方法
2020-09-05 13:22:27复习多线程的时候,练习了下,顺便记录一下: -
java多线程批量下载文件
2021-02-12 09:45:41多线程下载文件平时开发中有时会用到文件下载,为了提高文件的下载速率,采用多线程下载能够达到事半功倍的效果: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();
}
}
}
}
}
效果展示:
详细配置信息可以参考这篇文章:
-
java socket多线程文件传输实例项目
2016-08-10 11:04:25使用java socket开发的多线程文件上传下载的实例项目,多线程并发测试中可以支持200个,可能由于我电脑的配置问题,一般在并发大于200时client端可能会出现"阻塞"问题,还请大家指教 -
java使用多线程读取超大文件
2021-03-09 09:13:17在读取超过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实现网络多线程文件下载
2020-09-02 14:42:17主要介绍了Android实现网络多线程文件下载的相关资料,需要的朋友可以参考下 -
Java实现多线程断点下载
2020-08-27 20:55:52主要为大家详细介绍了Java实现多线程断点下载的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
Java URLConnection类 实现多线程下载文件
2020-05-12 13:57:28多线程下载文件是很实用的加速技巧,今天介绍多线程下载文件 前文回顾 【Java 两种简单的方式实现多线程】 【Java ExecutorService管理线程池的简单用法】 【JAVA URLConnection 实现下载小文件】 单一线程下载文件... -
JAVA实现大文件多线程下载,提速30倍!
2021-08-31 09:03:23JAVA实现大文件多线程下载,提速30倍! 前言 兄弟们看到这个标题可能会觉得是个标题党,为了解决疑虑,我们先来看下最终的测试结果: 测试云盘下载的文件 46M,自己本地最大下载速度 2M 1. 单线程下载,总耗时: 603s... -
java多线程导出excel(千万级别)优化
2018-12-05 14:29:01轻松解决普通poi形式导出Excel的中出现的栈溢出问题,此资源可实现千万级数据分批导出csv文件,csv大数据量导出(千万级别,不会内存溢出),多线程导出 ,生产环境已经很稳定的使用着 -
多线程导出Excel(百万级别)_Java版优化.zip
2019-09-10 22:39:38用开源 Apache POI 技术导出Excel,解决导出大数据出现OOM、栈溢出问题,此资源可实现百万级数据多线程分批导出Excel文件,不会内存溢出,生产环境已很稳定的使用者,所以用到的技术很核心、值得参考 -
java用多线程实现复制文件的功能
2020-02-23 15:54:20使用多线程实现多个文件同步复制功能,并在控制台显示复制的进度,进度以百分比表示。 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 ...本程序很适合在主机间批量传输文件和目录,参数可控 -
java-多线程下载器(支持断点续传、线程加减)包含源码和可运行jar包 第二版
2019-11-28 04:21:182、支持多任务多线程同时下载; 3、每个任务的线程数由用户在新建任务时自定义,缺省为5个线程; 4、任务下载过程中可以点击“线程+”或“线程-”即时增减线程; 5、选择任务,可以在任务信息栏中查看任务下载的信息...