精华内容
下载资源
问答
  • 主要为大家详细介绍了java多线程有序读取同一个文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了C#实现多线程写入同一个文件的方法,涉及C#多线程操作文件读写的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 新鲜出炉的SpringBoot版本的多线程下载文件,可以拿来整合SpringBoot项目或者SSM项目,可直接运行测试!!!
  • c++ 多线程同一个文本写入信息 解决同步与互斥问题
  • 1. 支持多线程: 多线程某时刻下载同一个文件的不同块. 2. 断点续传: 如果下载一个文件的某些块(一半), 则下次下载时只需下载未完成的块;文件块的下载状态用控制文件记录. 块下载完成的先后顺序不一定是连续的. ...
  • 主要为大家详细介绍了java多线程读取多个文件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • vb.net多线程文件同时下载.rar 对象数组和线程数组为多文件同时下载提供了可能。 我们要的就是一个循环把所有的任务都分配到各个对象和线程中,剩下的就让CPU去完成吧! 一个文件下载占用一个线程,同时进行。
  • 一个多线程分块下载文件工具。网上的一些代码可能会有些奇怪的问题,用的是类全局变量打开文件但在多线程中并未加锁,会导致文件有一定几率出现大小和源文件不同,即使文件大小相同,MD5值也不同,中间有段是坏的...
  • Aandroid 多线程断点续传同时下载文件
  • 多线程同时下载文件即:在同一时间内通过多线程对同一个请求地址发起多请求,将需要下载的数据分割成多部分,同时下载,每线程只负责下载其中的部分,最后将每一个线程下载的部分组装起来即可。...
  • 通过程序创建两个线程一个线程负责从文件”stat.c”读入数据,另一个线程负责显示读出的文件内容,每次读入 n 字节,n 从键盘输入。
  • java 多个线程同时写同一个文件

    千次阅读 2019-10-11 17:00:17
    话不说,先直接上代码: 主方法: import java.util.concurrent.CountDownLatch; /** * @ProjectName: emp_customer * @Package: PACKAGE_NAME * @ClassName: Test * @Author: Administrator * @...

    话不多说,先直接上代码:

    主方法:

    import java.util.concurrent.CountDownLatch;
    
    /**
     * @ProjectName: emp_customer
     * @Package: PACKAGE_NAME
     * @ClassName: Test
     * @Author: Administrator
     * @Description: ${description}
     * @Date: 2019/10/11 14:10
     * @Version: 1.0
     */
    public class Test {
         public static void main(String args[]){
    
             //线程数
             int threadSize=4;
             //源文件地址
             String sourcePath = "E:\\1\\4.txt";
             //目标文件地址
             String destnationPath = "E:\\2\\4.txt";
             //
             CountDownLatch latch = new CountDownLatch(threadSize);
             MultiDownloadFileThread m = new MultiDownloadFileThread(threadSize, sourcePath, destnationPath, latch);
             long startTime = System.currentTimeMillis();
             try {
                 m.excute();
                 latch.await();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             long endTime = System.currentTimeMillis();
             System.out.println("全部下载结束,共耗时" + (endTime - startTime) / 1000 + "s");
         }
    
    }
    

     

    线程类:

    import java.io.*;
    import java.nio.channels.FileChannel;
    import java.nio.channels.FileLock;
    import java.util.concurrent.CountDownLatch;
    
    /**
     * @ProjectName: emp_customer
     * @Package: PACKAGE_NAME
     * @ClassName: MultiDownloadFileThread
     * @Author: Administrator
     * @Description: ${description}
     * @Date: 2019/10/11 15:03
     * @Version: 1.0
     */
    public class MultiDownloadFileThread {
    
        private int threadCount;
        private String sourcePath;
        private String targetPath;
        private CountDownLatch latch;
    
        public MultiDownloadFileThread(int threadCount, String sourcePath, String targetPath, CountDownLatch latch) {
            this.threadCount = threadCount;
            this.sourcePath = sourcePath;
            this.targetPath = targetPath;
            this.latch = latch;
        }
    
        public void excute() {
            File file = new File(sourcePath);
            int fileLength = (int) file.length();
            //分割文件
            int blockSize = fileLength / threadCount;
            for (int i = 1; i <= threadCount; i++) {
                //第一个线程下载的开始位置
                int startIndex = (i - 1) * blockSize;
                int endIndex = startIndex + blockSize - 1;
                if (i == threadCount) {
                    //最后一个线程下载的长度稍微长一点
                    endIndex = fileLength;
                }
                System.out.println("线程" + i + "下载:" + startIndex + "字节~" + endIndex + "字节");
                new DownLoadThread(i, startIndex, endIndex).start();
            }
        }
    
    
        public class DownLoadThread extends Thread {
            private int i;
            private int startIndex;
            private int endIndex;
    
            public DownLoadThread(int i, int startIndex, int endIndex) {
                this.i = i;
                this.startIndex = startIndex;
                this.endIndex = endIndex;
            }
    
            @Override
            public void run() {
                File file = new File(sourcePath);
                FileInputStream in = null;
                RandomAccessFile raFile = null;
                FileChannel fcin = null;
                FileLock flin = null;
                try {
                    in = new FileInputStream(file);
                    in.skip(startIndex);
                    //给要写的文件加锁
                    raFile = new RandomAccessFile(targetPath, "rwd");
                    fcin =raFile.getChannel();
                    while(true){
                        try {
                            flin = fcin.tryLock();
                            break;
                        } catch (Exception e) {
                            System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒,当前进入的线程为:"+i);
                            sleep(1000);
                        }
                    }
                    //随机写文件的时候从哪个位置开始写
                    raFile.seek(startIndex);
                    int len = 0;
                    byte[] arr = new byte[1024];
                    //获取文件片段长度
                    int segLength = endIndex - startIndex + 1;
                    while ((len = in.read(arr)) != -1) {
                        if (segLength > len) {
                            segLength = segLength - len;
                            raFile.write(arr, 0, len);
                        } else {
                            raFile.write(arr, 0, segLength);
                            break;
                        }
                    }
                    System.out.println("线程" + i + "下载完毕");
                    //计数值减一
                    latch.countDown();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (in != null) {
                            in.close();
                        }
                        if (raFile != null) {
                            raFile.close();
                        }
    
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    运行结果:

     

    涉及到的相关知识点:

    1.CountDownLatch 

    2.RandomAccessFile

    3.FileLock

    下面我们具体讲解下

    一、FileLock :文件锁

    FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w)加锁,保证同时只有一个进程可以拿到文件的锁,这个进程从而可以对文件做访问;而其它拿不到锁的进程要么选择被挂起等待,要么选择去做一些其它的事情, 这样的机制保证了众进程可以顺序访问该文件。

    1. 概念

    • 共享锁: 共享读操作,但只能一个写(读可以同时,但写不能)。共享锁防止其他正在运行的程序获得重复的独占锁,但是允许他们获得重复的共享锁。
    • 独占锁: 只有一个读或一个写(读和写都不能同时)。独占锁防止其他程序获得任何类型的锁。

    2. lock()和tryLock()的区别:

    lock()阻塞的方法,锁定范围可以随着文件的增大而增加。无参lock()默认为独占锁;有参lock(0L, Long.MAX_VALUE, true)为共享锁。
    tryLock()非阻塞,当未获得锁时,返回null.
    3. FileLock的生命周期:在调用FileLock.release(),或者Channel.close(),或者JVM关闭

    4. FileLock是线程安全的
     

    二、RandomAccessFile

    java除了File类之外,还提供了专门处理文件的类,即RandomAccessFile(随机访问文件)类。该类是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法。RandomAccessFile类支持“随机访问”方式,这里“随机”是指可以跳转到文件的任意位置处读写数据。在访问一个文件的时候,不必把文件从头读到尾,而是希望像访问一个数据库一样“随心所欲”地访问一个文件的某个部分,这时使用RandomAccessFile类就是最佳选择。

    RandomAccessFile对象类有个位置指示器,指向当前读写处的位置,当前读写n个字节后,文件指示器将指向这n个字节后面的下一个字节处。刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写操作将从新的位置开始。RandomAccessFile类在数据等长记录格式文件的随机(相对顺序而言)读取时有很大的优势,但该类仅限于操作文件,不能访问其他的I/O设备,如网络、内存映像等。RandomAccessFile类的构造方法如下所示:

    RandomAccessFile(File file ,  String mode)
    //创建随机存储文件流,文件属性由参数File对象指定

    RandomAccessFile(String name ,  String mode)
    //创建随机存储文件流,文件名由参数name指定

    这两个构造方法均涉及到一个String类型的参数mode,它决定随机存储文件流的操作模式,其中mode值及对应的含义如下:

    “r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
    “rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
    “rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
    “rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作

     

    三、CountDownLatch

    1.概念

    • countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
    • 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

    2.源码

    • countDownLatch类中只提供了一个构造器:
    //参数count为计数值
    public CountDownLatch(int count) {  };  
    
    • 类中有三个方法是最重要的:
    //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
    public void await() throws InterruptedException { };   
    //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
    //将count值减1
    public void countDown() { };  

    假如在我们的代码里面,我们把main方法里面的

    latch.await();

    注释掉

    如下所示:

    我们可以看到跟之前的输出结果相比,我们的主方法里面输出的:全部下载结束的输出信息,已经打印到我们执行文件下载的线程输出信息的前面了,说明主线程先执行完。这从而说明,await() 方法具有阻塞作用

     我们在把latch.await();放开,把文件下载线程里的latch.countDown();注释掉,

    如下:

    我们可以看到,主程序里的的输出;全部下载结束的输出信息,一直未输出,程序也一直未结束,由此可得,countDown() 方法具有唤醒阻塞线程的作用。

    那么如何让 CountdownLatch 尽早结束

    假如我们的程序执行到countDown()之前就抛出异常,这就可能导致一整情况,CountdownLatch 计数永远不会达到零并且 await() 永远不会终止。

    为了解决这个问题,我们在调用 await() 时添加一个超时参数。

     

    CountDownLatch总结:

        1、CountDownLatch end = new CountDownLatch(N); //构造对象时候 需要传入参数N

      2、end.await()  能够阻塞线程 直到调用N次end.countDown() 方法才释放线程,最好设置超时参数

      3、end.countDown() 可以在多个线程中调用  计算调用次数是所有线程调用次数的总和

     

    对于,本demo而言,加不加文件锁的意义不大,因为在进入线程写的时候,就已经告诉单个线程需要写的内容是哪一块到哪一块,不加锁,也会正常写入,切经本人测试无误,但若是对同一个文件,即要写,又要读话,就必须加锁,不然程序执行可能不完整,具体情况可以查看下面的这个博客:https://blog.csdn.net/gxy3509394/article/details/7435993

    展开全文
  • java的ftp多线程下载

    热门讨论 2014-10-02 20:42:47
    本程序是在原有基础上逐步完善的,第版:http://download.csdn.net/detail/zpwmhx/4342943 第二版:http://download.csdn.net/detail/zpwmhx/4505209 ...本程序很适合在主机间批量传输文件和目录,参数可控
  • 多线程分别下载文件

    2013-08-15 17:11:03
    这是一个在listview或gridview中选项同时分别下载文件的demo。 每选项进度条分别更新进度。
  • 采用C语言, 多线程同一个文件进行写操作; * 2.每线程有自己的写入位置; * 3.每线程有自己的数据缓冲区; * 4.写文件前, 会 加锁(全局变量), 然后 将文件句柄 跳跃到指定位置, 写下线程缓冲区的数据;...
  • 前几天,朋友托我帮忙,问我能不能用多线程的方式,读取一个文件,获取里面的内容。...所以,他就问我要怎么多线程读取同一个文件里面的内容,形成多生产者-多消费者的模型,从而提高速度。  因此

      前几天,朋友托我帮个忙,问我能不能用多线程的方式,读取一个文件,获取里面的内容。他大概想做的事情,就是读取文件里面每一行的内容,然后分析一下,再插入到数据库这样。但是,由于他那个记录内容的文件实在是太大了,虽然他弄成了单生产者-多消费者的模型,整体的处理速度还是非常的慢,因为读取速度不够快。所以,他就问我要怎么多线程读取同一个文件里面的内容,形成多生产者-多消费者的模型,从而提高速度。

      因此就有了下面的demo试的代码,只要传一个文件路径,读取文件的线程数,分隔符,回调这4个参数即可,并且还配上了测试代码。


     下面是我本地跑出来的测试结果(测试文件,是一个190MB大的文件):

    3线程(本机2核4线程) 耗时 3231498毫秒
    2线程 耗时 278592毫秒
    单线程 耗时397115毫秒
    cpu线程数(4线程)耗时245657 毫秒


    package demo.demo;
    
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.io.UnsupportedEncodingException;
    import java.security.InvalidParameterException;
    import java.util.Random;
    import java.util.UUID;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class ThreadReadFileHelper {
    	// 模拟数据
    	private static void writeData() throws FileNotFoundException, IOException {
    		FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\lianghaohui\\Desktop\\test.txt");
    		Random random = new Random();
    		for (int n = 0; n < 1000000; n++) {
    			int count = random.nextInt(10) + 1;
    			StringBuilder builder = new StringBuilder();
    
    			for (int i = 0; i < count; i++) {
    				builder.append(UUID.randomUUID().toString());
    			}
    
    			builder.append("\n");
    			fileOutputStream.write(builder.toString().getBytes());
    		}
    		fileOutputStream.close();
    		System.out.println("ok");
    	}
    
    	private static AtomicInteger atomicInteger = new AtomicInteger(0);
    
    	// 231498耗时 3线程(本机2核4线程)
    	// 278592耗时 2线程
    	// 397115耗时 单线程
    	// 245657耗时 cpu线程数(4线程)
    	public static void main(String[] args) throws Exception {
    		long beginTime = System.currentTimeMillis();
    		ThreadReadFileHelper helper = new ThreadReadFileHelper();
    		helper.read("C:\\Users\\lianghaohui\\Desktop\\test.txt", Runtime.getRuntime().availableProcessors(), '\n', new StringCallback("UTF-8") {
    			@Override
    			void callback(String data) {
    				int count = atomicInteger.incrementAndGet();
    				System.out.println(count);
    				if (count == 1000000) {
    					System.out.println("总耗时毫秒:" + (System.currentTimeMillis() - beginTime));
    					System.out.println(data);
    				}
    			}
    		});
    
    		// RandomAccessFile randomAccessFile = new RandomAccessFile("C:\\Users\\lianghaohui\\Desktop\\test.txt", "r");
    		// while (true) {
    		// if (randomAccessFile.readLine() == null) {
    		// System.out.println("总耗时毫秒:" + (System.currentTimeMillis() - beginTime));
    		// break;
    		// } else {
    		// int count = atomicInteger.incrementAndGet();
    		// System.out.println(count);
    		// }
    		// }
    		// randomAccessFile.close();
    	}
    
    	public void read(String path, int threadCount, char separator, StringCallback callback) throws IOException {
    
    		if (threadCount < 1) {
    			throw new InvalidParameterException("The threadCount can not be less than 1");
    		}
    
    		if (path == null || path.isEmpty()) {
    			throw new InvalidParameterException("The path can not be null or empty");
    		}
    
    		if (callback == null) {
    			throw new InvalidParameterException("The callback can not be null");
    		}
    
    		RandomAccessFile randomAccessFile = new RandomAccessFile(path, "r");
    
    		long fileTotalLength = randomAccessFile.length();
    		long gap = fileTotalLength / threadCount;
    		long checkIndex = 0;
    		long[] beginIndexs = new long[threadCount];
    		long[] endIndexs = new long[threadCount];
    
    		for (int n = 0; n < threadCount; n++) {
    			beginIndexs[n] = checkIndex;
    			if (n + 1 == threadCount) {
    				endIndexs[n] = fileTotalLength;
    				break;
    			}
    			checkIndex += gap;
    			long gapToEof = getGapToEof(checkIndex, randomAccessFile, separator);
    
    			checkIndex += gapToEof;
    			endIndexs[n] = checkIndex;
    		}
    
    		ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
    		executorService.execute(() -> {
    			try {
    				readData(beginIndexs[0], endIndexs[0], path, randomAccessFile, separator, callback);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		});
    
    		for (int n = 1; n < threadCount; n++) {
    			long begin = beginIndexs[n];
    			long end = endIndexs[n];
    			executorService.execute(() -> {
    				try {
    					readData(begin, end, path, null, separator, callback);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			});
    		}
    	}
    
    	private long getGapToEof(long beginIndex, RandomAccessFile randomAccessFile, char separator) throws IOException {
    		randomAccessFile.seek(beginIndex);
    		long count = 0;
    
    		while (randomAccessFile.read() != separator) {
    			count++;
    		}
    
    		count++;
    
    		return count;
    	}
    
    	private void readData(long begin, long end, String path, RandomAccessFile randomAccessFile, char separator, StringCallback callback) throws FileNotFoundException, IOException {
    		System.out.println("开始工作" + Thread.currentThread().getName());
    		if (randomAccessFile == null) {
    			randomAccessFile = new RandomAccessFile(path, "r");
    		}
    
    		randomAccessFile.seek(begin);
    		StringBuilder builder = new StringBuilder();
    
    		while (true) {
    			int read = randomAccessFile.read();
    			begin++;
    			if (separator == read) {
    				if (callback != null) {
    					callback.callback0(builder.toString());
    				}
    				builder = new StringBuilder();
    			} else {
    				builder.append((char) read);
    			}
    
    			if (begin >= end) {
    				break;
    			}
    		}
    		randomAccessFile.close();
    	}
    
    	public static abstract class StringCallback {
    		private String charsetName;
    		private ExecutorService executorService = Executors.newSingleThreadExecutor();
    
    		public StringCallback(String charsetName) {
    			this.charsetName = charsetName;
    		}
    
    		private void callback0(String data) {
    			executorService.execute(() -> {
    				try {
    					callback(new String(data.getBytes("ISO-8859-1"), charsetName));
    				} catch (UnsupportedEncodingException e) {
    					e.printStackTrace();
    				}
    			});
    
    		}
    
    		abstract void callback(String data);
    	}
    
    }
    


    展开全文
  • Android多线程文件上传

    2018-12-01 06:46:46
    多线程同时下载文件即:在同一时间内通过多线程对同一个请求地址发起多请求,将需要下载的数据分割成多部分,同时下载,每线程只负责下载其中的部分,最后将每一个线程下载的部分组装起来即可。
  • 使用多进程/多线程同时下载单个文件,可以自定义文件地址、进程/线程数量。 主要思路: 获取文件大小,使用多进程/线程分别下载一部分,最后再把这些文件拼接起来。 参考代码: 运行结果: ---董付国...

    功能描述:

    使用多进程/多线程同时下载单个文件,可以自定义文件地址、进程/线程数量。

    主要思路:

    获取文件大小,使用多个进程/线程分别下载一部分,最后再把这些文件拼接起来。

    参考代码:

    运行结果:

     

    ---董付国老师Python系列图书---

    友情提示:不建议购买太多,最好先通过京东、当当、天猫查阅图书了解目录和侧重点,然后再选择购买适合自己的书。

    (1)《Python程序设计(第2版)》(ISBN:978-7-302-43651-5),清华大学出版社,2016年8月出版,2019年度清华大学出版社畅销图书

    (2)《Python可以这样学》(ISBN:978-7-302-45646-9),清华大学出版社,2017年2月

    (3)《Python程序设计基础(第2版)》(ISBN:978-7-302-49056-2)清华大学出版社,2018年1月出版,2019年度清华大学出版社畅销图书

    (4)《中学生可以这样学Python》(ISBN:978-7-302-48039-6)清华大学出版社

    (5)《Python程序设计开发宝典》(ISBN:978-7-302-47210-0)清华大学出版社,2018年10月

    (6)《玩转Python轻松过二级》(ISBN:978-7-302-49916-9)清华大学出版社,2018年5月

    (7)《Python程序设计基础与应用》(ISBN:978-7-111-60617-8),机械工业出版社,2018年9月

    (8)《Python程序设计实验指导书》(ISBN:9787302525790),清华大学出版社,2019年4月

    (9)《Python编程基础与案例集锦(中学版)》(ISBN:978-7-121-35539-4),电子工业出版社,2019年4月

    (10)《大数据的Python基础》(ISBN:978-7-111-62455-4),机械工业出版社,预计2019年5月出版

    (11)译作《Python程序设计》,机械工业出版社(华章),2018年11月出版

    (12)繁体版《Python也可以这样学》,台湾博硕文化股份有限公司,2017年10月出版,本书为《Python可以这样学》在台湾发行的繁体版,两本书内容一样,不建议重复购买。

    (13)《Python程序设计实例教程》(ISBN:978-7-111-63198-9),机械工业出版社

    (14)《Python数据分析、挖掘与可视化》(ISBN:978-7-115-52361-7),人民邮电出版社,2019年12月

    展开全文
  • (Java)FTP多线程下载源代码

    热门讨论 2011-08-21 22:41:52
    实现了FTP多线程下载,并有简单的包括进度条的界面,代码的运行:1 把自己的PC配置成FTP服务器(只需下载Serc-U软件)2 建立用户,用户名:zhangyu,密码:123,设置根目录,并拷贝进一些文件(这就是FTP服务器上的要...
  • 具体实现思路就举列子说明吧: 假设有10000字节需要写入某个文件,为了加快写入速度,可以开启2个线程,第一个线程将前5000字节写入文件0~4999的位置,另外一个线程将后5000字节写入文件5000~9999的位置,等...

    本文给出了一个如何利用java提供的类MappedByteBuffer对文件进行并发写入的例子。具体实现思路就举个列子说明吧: 假设有10000个字节需要写入某个文件,为了加快写入速度,可以开启2个线程,第一个线程将前5000个字节写入文件0~4999的位置,另外一个线程将后5000个字节写入文件5000~9999的位置,等2个线程都写入完成后。我们就成功的将10000个字节完整的写入到了文件中。

    值得一提的是,线程在写入过程中是会对自己所占用的那个文件区域枷锁的。各个线程加锁的区域互不重叠,否则会报OverlappingFileLockException异常

    这个例子读者可以直接运行main方法查看效果,该类无任何外部依赖,全是jdk自带api。待写入的内容用源码中CONTENS字段表示,该字段记录了欧阳修名作《秋声赋》的完整内容。程序运行结束后可以到D盘查找名为ConcurrentWrite.txt的文件查看写入结果(D://ConcurrentWrite.txt),当然了,前提是你的电脑存在D盘。

    程序不是很复杂,直接贴源码吧,关键地方有注释。另外,目标文件ConcurrentWrite.txt在程序运行期间不能被其他外部程序打开,否则写入失败!!!!

    package com.lhever.modules.io.test;
    
    
    import java.io.*;
    import java.lang.reflect.Method;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.FileLock;
    import java.nio.channels.OverlappingFileLockException;
    import java.security.AccessController;
    import java.security.PrivilegedAction;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    
    public class MappedByteBufferTest {
    
        //该字符串的内容将会被多线程写入到文件中
        static String CONTENS = "【作者】欧阳修 【朝代】宋 译文对照\n" +
                "欧阳子方夜读书,闻有声自西南来者,悚然而听之,曰:“异哉!”初淅沥以萧飒,忽奔腾而砰湃,如波涛夜惊,风雨骤至。其触于物也,鏦鏦铮铮,金铁皆鸣;又如赴敌之兵,衔枚疾走,不闻号令,但闻人马之行声。予谓童子:“此何声也?汝出视之。”童子曰:“星月皎洁,明河在天,四无人声,声在树间。”\n" +
                "\n" +
                "予曰:“噫嘻悲哉!此秋声也,胡为而来哉?盖夫秋之为状也:其色惨淡,烟霏云敛;其容清明,天高日晶;其气栗冽,砭人肌骨;其意萧条,山川寂寥。故其为声也,凄凄切切,呼号愤发。丰草绿缛而争茂,佳木葱茏而可悦;草拂之而色变,木遭之而叶脱。其所以摧败零落者,乃其一气之余烈。夫秋,刑官也,于时为阴;又兵象也,于行用金,是谓天地之义气,常以肃杀而为心。天之于物,春生秋实,故其在乐也,商声主西方之音,夷则为七月之律。商,伤也,物既老而悲伤;夷,戮也,物过盛而当杀。”\n" +
                "\n" +
                "“嗟乎!草木无情,有时飘零。人为动物,惟物之灵;百忧感其心,万事劳其形;有动于中,必摇其精。而况思其力之所不及,忧其智之所不能;宜其渥然丹者为槁木,黟然黑者为星星。奈何以非金石之质,欲与草木而争荣?念谁为之戕贼,亦何恨乎秋声!”\n" +
                "\n" +
                "童子莫对,垂头而睡。但闻四壁虫声唧唧,如助予之叹息耶。";
    
    
        public static void await(CountDownLatch latch) {
            if (latch == null) {
                return;
            }
    
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    
    
        public static void main(String... args) {
    
            File file = getByName("D://ConcurrentWrite.txt");
            byte[] bytes = null;
            try {
                bytes = CONTENS.getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
    
            int len = bytes.length;
            System.out.println("len: " + len);
            int concurrentNum = 4;
    
            if (len < concurrentNum) {
                concurrentNum = 1;
            } else {
                concurrentNum = (len % concurrentNum == 0) ? concurrentNum : (concurrentNum + 1);
            }
    
            int size = len / concurrentNum;
    
            List<FileBlockWriter> writers = new ArrayList<FileBlockWriter>();
    
            CountDownLatch startLatch = new CountDownLatch(1);
            CountDownLatch endLatch = new CountDownLatch(concurrentNum);
    
            for (int i = 0; i < concurrentNum; i++) {
                FileBlockWriter writer = null;
    
                int from = i * size;
                int sliceLen = 0;
                System.out.println(from);
    
                if (i == concurrentNum - 1) {
                    sliceLen = bytes.length - i * size;
                    System.out.println(sliceLen);
                } else {
                    sliceLen = size;
                }
    
                byte[] slice = new byte[sliceLen];
                System.arraycopy(bytes, from, slice, 0, sliceLen);
                writer = new FileBlockWriter(file, from, sliceLen, slice, startLatch, endLatch);
    
                writers.add(writer);
            }
    
            for (FileBlockWriter writer : writers) {
                writer.start();
            }
    
            //调用countDown后,所有写入线程才真正开始写入工作
            startLatch.countDown();
    
            //等待所有线程写入完成
            await(endLatch);
    
            System.out.println("done !!! ");
    
    
        }
    
    
        private static File getByName(String path) {
    
            File file = new File(path);
    
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    throw new IllegalArgumentException("create file failed", e);
                }
            }
    
            if (file.isDirectory()) {
                throw new IllegalArgumentException("not a file");
            }
    
            return file;
        }
    
    
        /**
         * 该线程类负责将指定的内容(contents)写入文件(target),
         * 写入的起始位置是:from,往后写的字节数目是:length
         */
        public static class FileBlockWriter extends Thread {
    
            private File target;
            private int from;
            private int length;
            private byte[] contents;
            private CountDownLatch start;
            private CountDownLatch end;
    
            public FileBlockWriter(File target, int from, int length, byte[] contents, CountDownLatch start, CountDownLatch end) {
                this.target = target;
                this.from = from;
                this.length = length;
                this.contents = contents;
                this.start = start;
                this.end = end;
            }
    
            @Override
            public void run() {
    
                RandomAccessFile randFile = null;
                FileChannel channel = null;
                MappedByteBuffer mbb = null;
                FileLock fileLock = null;
    
                MappedByteBufferTest.await(start);
    
                try {
    
                    randFile = new RandomAccessFile(target, "rw");
                    channel = randFile.getChannel();
                    mbb = channel.map(FileChannel.MapMode.READ_WRITE, from, length);
    
                    fileLock = channel.lock(from, length, true);
    
                    while (fileLock == null || !fileLock.isValid()) {
                        fileLock = channel.lock(from, length, true);
                        System.out.print("锁无效,重复获取");
                    }
                    mbb.put(contents);
                    mbb.force();
    
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (OverlappingFileLockException e) {
                    e.printStackTrace();
                    throw new IllegalArgumentException("程序设计不合理,加锁区域相互重叠");
    
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
    
                    release(fileLock);
                    forceClose(mbb);
                    close(channel, randFile);
                }
    
                end.countDown();
            }
        }
    
    
        private static void release(FileLock fileLock) {
            if (fileLock == null) {
                return;
            }
    
            try {
                fileLock.release();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private static void close(Closeable... closeables) {
    
    
            if (closeables == null || closeables.length == 0) {
                return;
            }
    
            for (Closeable closeable : closeables) {
                if (closeable == null) {
                    continue;
                }
                try {
                    closeable.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 强制关闭MappedByteBuffer
         * @param mbb
         */
        private static void forceClose(MappedByteBuffer mbb) {
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    try {
                        Method getCleanerMethod = mbb.getClass().getMethod("cleaner", new Class[0]);
                        getCleanerMethod.setAccessible(true);
                        sun.misc.Cleaner cleaner = (sun.misc.Cleaner)
                                getCleanerMethod.invoke(mbb, new Object[0]);
                        cleaner.clean();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                }
            });
        }
    
    
    }
    
    879675643@qq.com  lhever
    
    .---.                                                                         
    |   |   .              __.....__   .----.     .----.   __.....__              
    |   | .'|          .-''         '.  \    \   /    /.-''         '.            
    |   |<  |         /     .-''"'-.  `. '   '. /'   //     .-''"'-.  `. .-,.--.  
    |   | | |        /     /________\   \|    |'    //     /________\   \|  .-. | 
    |   | | | .'''-. |                  ||    ||    ||                  || |  | | 
    |   | | |/.'''. \\    .-------------''.   `'   .'\    .-------------'| |  | | 
    |   | |  /    | | \    '-.____...---. \        /  \    '-.____...---.| |  '-  
    |   | | |     | |  `.             .'   \      /    `.             .' | |      
    '---' | |     | |    `''-...... -'      '----'       `''-...... -'   | |      
          | '.    | '.                                                   |_|      
          '---'   '---'  
    展开全文
  • HTTP大文件多线程下载工具,支持断点续传
  • python多线程读取同一个文件

    万次阅读 2015-05-13 21:36:05
    python多线程读取同一个文件 多线程读取同一个文件,要求不能重复,不能遗漏。 最开始尝试了种方法(后来实践证明是无效的) 主线程分配给每读线程需要读取文件中哪些行, 比如线程1读取1-10行,线程2...
  • java多线程下载

    2014-05-27 11:13:54
    1.得到服务器下载文件的大小,然后在本地设置一个临时文件和服务器端文件大小一致 a)获得访问网络地址 b)通过URL对象的openConnection()方法打开连接,返回一个连接对象 c)设置请求头 i.setRequestMethod ii....
  • 今天遇到一个问题,需要多线程读取同一个文件的不同位置,提高效率,写代码验证了一下,把结果记录下来。 首先我们写个文件,然后多线程读取,以下是我实验的代码:package com.alibaba.middleware.race;import ...
  • 知识目录 &amp;amp;lt;?php $fp = fopen(&amp;quot;/tmp/lock.txt&amp;quot;, &amp;quot;w+&amp;quot;); if(flock($fp, LOCK_EX)){ // 进行排它型锁定 ... flock($fp, LOCK_U
  • 项目中用到分段文件下载,也使用多线程下载,提高下载效率。 自己花了时间整合成一个项目,可直接执行Junit方法看效果。
  • java多线程读有序地读取同一个文件

    千次阅读 2019-05-16 14:13:44
    本人刚参加工作,面试的时候遇四道笔试题,其中就有这道多线程有序读取文件的题目,初看时拿不准,感觉会,有感觉不会。于是放弃了这道题,今天闲下来好好做遍。 //定义一个runnable接口的实现类 import java.io....
  • java实现多线程下载文件功能,通过线程池管理,实现下载文件速度快,安全。
  • C#实现多线程下载文件,结合多线程技术的各方面知识,是比较好的学习例子。
  • java多线程下载文件

    2011-10-12 12:25:17
    java多线程断点下载文件 ,文档介绍及代码实现

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,101,325
精华内容 440,530
关键字:

多线程下载同一个文件