本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/867469
这个标题可能有些歧义,我也不知道该取什么标题,知道的同学帮忙取下.同时这只是我平时的一个总结,
问题估计会有很多,大家帮忙指正,谢谢!
这里先说下应用场景,比如:
1)需要一直处理一个文件目录,处理里面的文件.文件过多,单线程恐怕速度跟不上,于是使用多线程.
2)网络下载,需要下载很多URL.单线程也是速度跟不上,于是一个URL用一个线程去下载并处理(如爬虫,这也是我写爬虫的总结).
再说下如何高效安全:
1)以上不可能每一个文件,每一个URL就开一个线程去处理.肯定是先初始化一个线程池,然后将文件、URL放入一个容器(比如队列),然后线程从容器里获取数据去处理,处理完了,就再获取,如此直到处理完毕.
2)可能文件或者URL的数据会很大,足让你内存溢出.或者多个线程的数据加起来也足以让你内存爆掉.那肯定要设置内存装载的数据大小限制,也就是所谓的缓存。当缓存写满了,再考虑写入文件.
3)由于线程固定,缓存也是固定,写入的文件也是固定.那这些都是可循环利用的对象。不可能每一次处理都是new,那是极大的浪费。所以可以固定线程的个数,缓存的大小(可以控制内存大小),甚至那个备份文件也是一直可以循环所有的对象
所需要的东西:
1)干活的线程
2)接活的容器
3)线程池
4)可将数据放入内存达到一定阀值后再写入文件的类,同时提供返回数据的功能(内存和文件里的数据都得返回).返回数据也有多种形式,字符串、流?同时也得考虑循环利用,毕竟也是固定的
5)附加功能:
a.内容可以指纹化(MD5或SHA1)
b.可以如InputStream的mark,reset等.毕竟这一切都可以当做输入输出流来处理,我接下来的代码也是
c.可以控制处理的速度,比如这个场景是下载URL(网络爬虫),我不想下载速度过快.
d.待补充
大概的设计:
1)干活的线程 MyThread
2)接活的容器 具体看你的应用,例子里有
3)线程池 具体也看你的应用,我这里只是测试代码里弄个线程组
4)处理数据的类:
a.读数据到内存或文件中的类:MyOutputStream
b.MyOutputStream里面又要返回数据的类:MyInputStream
接下来开始贴代码了.
1)可以读取数据,如果数据过多达到缓存,可以写入文件的类
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class MyOutputStream extends OutputStream { private boolean isOpen; // 是否已经打开 private long size; // 数据总大小 private String backedFileName; // 超出缓存,要写入到的文件名 private OutputStream diskStream;// 超出缓存,写入到文件的OutputStream private byte[] buffer; // 缓存 private long position; // 当前位置 private boolean recording; // 是否记录数据中 public MyOutputStream(int bufferSize,String backedFileName){ this.buffer=new byte[bufferSize]; this.backedFileName=backedFileName; this.recording=true; } public void open() throws IOException{ if(isOpen()){ throw new IOException("MyOutputStream already open for ".concat(Thread.currentThread().getName())); } isOpen=true; this.position=0; this.size=0; this.recording=true; closeDiskStream(); this.diskStream=new FileOutputStream(this.backedFileName); } private void closeDiskStream() throws IOException{ if(this.diskStream!=null){ diskStream.close(); diskStream=null; } } public void closeRecorder() throws IOException{ recording=false; closeDiskStream(); if(this.size==0){ this.size=position; } } public boolean isOpen(){ return isOpen; } // 记录一个字节 private void record(int b) throws IOException{ if(this.position>=this.buffer.length){ this.diskStream.write((byte)b); }else{ buffer[(int)position]=(byte)b; } this.position++; } // 记录多个字节 private void record(byte[] b,int off,int len) throws IOException{ if(position>=this.buffer.length){ // 如果缓存已经满了,则写入硬盘 if(this.diskStream==null){ throw new IOException("diskStream is null for ".concat(Thread.currentThread().getName())); } this.diskStream.write(b, off, len); // 写入硬盘 this.position+=len; // 位置增加 }else{ // 没满,则写入缓存.如果此时缓存写满了,则再写入磁盘 int toCopy=Math.min(this.buffer.length-(int)this.position, len); // 计算要写入缓存的长度,不让缓存爆掉 System.arraycopy(b, off, this.buffer, (int)this.position, len); // 拷贝到缓存 this.position+=toCopy; if(toCopy<len){ // 如果缓存已满,则将剩下的数据写入硬盘 //this.diskStream.write(b,off+toCopy,len-toCopy); record(b,off+toCopy,len-toCopy); // 为什么不直接用上一行代码?需要验证diskStream } } } // 写入数据 @Override public void write(int b) throws IOException { if(recording){ record(b); } } // 写入数据 @Override public void write(byte[] b, int off, int len) throws IOException { if(recording){ record(b,off,len); } } // 写入数据 @Override public void write(byte[] b) throws IOException { if(recording){ record(b,0,b.length); } } // 关闭,关闭了才能获得长度 @Override public void close() throws IOException { isOpen=false; closeRecorder(); } // 刷新 @Override public void flush() throws IOException { if(this.diskStream!=null){ this.diskStream.flush(); } } // 获得数据大小 public long getSize() { return size; } public static void main(String[] args) { String dir=new File("").getAbsolutePath().concat(File.separator); String fileMemory=dir.concat("fileMemory.txt"); String fileDisk=dir.concat("fileDisk.txt"); int bufferSize=5; MyOutputStream mosMemory=null; MyOutputStream mosDisk=null; try { mosMemory=new MyOutputStream(bufferSize,fileMemory); mosMemory.open(); mosDisk=new MyOutputStream(bufferSize,fileDisk); mosDisk.open(); for(int i=0;i<100;i++){ if(i<bufferSize){ mosMemory.write(i); } mosDisk.write(i); } mosMemory.close(); mosDisk.close(); System.out.println("mosMemory length:"+mosMemory.getSize()); System.out.println("mosDisk length:"+mosDisk.getSize()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ } } }
更多技术文章、感悟、分享、勾搭,请用微信扫描:
相关推荐
Java输入输出流(I/O流)是Java编程中不可或缺的一部分,它允许程序处理数据的读取、写入和传输。Java I/O系统基于流的概念,流可以被视为数据的有序序列,既可以是从源(如文件、网络连接)读取数据的输入流,也...
输入/输出处理数据的传输,而多线程则涉及程序的并发执行。 首先,让我们深入理解Java的IO系统。Java.IO包包含了大量用于处理输入和输出操作的类和接口。输入流(InputStream)和输出流(OutputStream)是这个包的...
Java中的输入输出流是程序与外部数据...总之,Java的输入输出流是其强大的特性之一,为开发者提供了灵活且高效的处理数据输入输出的能力。通过不断的实践和学习,我们可以掌握更多的IO技巧,更好地应对各种实际问题。
5. **I/O流**:在Java中,`InputStream`和`OutputStream`是用于读写文件的基础类,多线程传输时,每个线程可以拥有自己的输入/输出流实例,分别处理文件的一部分。 6. **异常处理**:多线程环境下,需要确保每个...
Java输入输出流是Java编程中不可或缺的部分,它用于应用程序与外部设备之间进行数据交换,比如磁盘、网络、键盘和显示器。I/O流是Java中处理输入和输出的基础框架,它提供了一种抽象的方式来处理不同类型的输入源和...
Java提供了丰富的I/O处理机制,包括标准输入输出流、字节流、字符流等多种方式来处理数据的读取和写入。标准输入输出流是Java中非常基础且重要的组成部分。 **1.1 标准输入输出流简介** - **System.out**: 是一个`...
然后,我们引入`java.nio`包,这个包提供了非阻塞I/O操作,使得在多线程环境下处理数据更高效。特别是`java.nio.channels.Channels`和`java.nio.file.Files`类,它们可以帮助我们将输入流转换为通道,并将数据写入到...
Java多线程文件传输是一个复杂而实用的编程概念,它结合了Java的Socket编程和Swing GUI库,用于实现高效的数据交换。在这个项目中,开发者创建了一个基于Socket的多线程文件传输系统,允许用户通过图形化用户界面...
"文件管理和输入输出流"这个主题涵盖了Java、C语言、C++、C#以及JSP等多种编程语言中的相关技术,这些技术使得程序员能够有效地读取、写入和处理文件数据。 首先,我们来探讨文件管理。文件管理主要包括创建、打开...
Java 输入输出流是Java编程语言中处理数据传输的基础机制,主要负责程序与外部资源(如文件、网络连接等)之间的数据交互。Java 提供了多种类型的流,它们分为两大类:字节流(处理单个字节的数据)和字符流(处理...
在Java中,输入输出流是一组类和接口,用于读取和写入数据到不同的源和目标,如文件、网络连接或内存。Java的IO流分为字节流和字符流两大类,字节流处理原始的8位字节数据,而字符流则处理Unicode字符。基本的输入流...
Java输入输出流是Java编程语言中的核心概念,用于在程序之间、程序与文件系统、网络连接等不同数据源之间传输数据。在这个主题中,我们将深入探讨Java输入输出流的使用,通过具体的代码示例帮助你理解和掌握这个关键...
3. **输入/输出流**:Java的IO流是处理数据输入和输出的基础,下载工具中通常会用到`InputStream`(用于读取服务器的数据)和`OutputStream`(用于将数据写入本地文件)。例如,我们可以使用`BufferedInputStream`和...
总的来说,Java的异常处理、多线程和流式输入输出与文件处理是编程中重要的概念,理解并熟练运用它们能帮助开发者编写更健壮、安全和高效的代码。对于初学者而言,通过阅读详细的教程和实践练习,可以逐步掌握这些...
综上所述,这份Java学习资料涵盖了从基础到高级的多个主题,包括基本语法、面向对象编程、异常处理、Applet、GUI设计、多线程以及输入输出流。对于想要系统学习Java的初学者,这是一份非常全面且深入的学习资源。...
### Java多线程网络传输文件(非同步) #### 概述 在现代软件开发中,尤其是在涉及大量数据传输的应用场景下,高效的文件传输方案尤为重要。Java作为一种广泛应用的编程语言,提供了丰富的工具和技术来实现高性能...
### Java输入输出流详解 #### 一、Java IO 概述 在计算机程序设计中,输入输出(Input/Output,简称IO)是非常重要的一个概念。它涉及到程序如何与外部世界进行数据交换,最常见的外部设备包括磁盘存储和网络通信等...
总的来说,这个实验将教会你如何在Java多线程环境中实现高效、稳定的文件上传和下载功能,这是一项对任何开发人员来说都非常实用的技能,尤其是在构建高性能的Web应用或后台服务时。通过实践和理解这些概念,你将...
Java多线程下载是利用Java编程语言实现的一种高效下载大文件的技术。在传统的单线程下载方式中,如果网络环境不稳定或文件较大,下载过程可能会很慢,甚至中断。而多线程下载则是将文件分割成多个部分,每个部分由一...
在Java编程语言中,输入输出流(Input/Output Stream)是处理数据传输的核心概念,而线程则是实现并发处理和程序高效运行的关键机制。这两者在构建高效、响应迅速的应用程序时都扮演着至关重要的角色。 输入输出流...