黑马程序员技术交流社区
标题:
多线程玩玩IO流,求开导。。。
[打印本页]
作者:
lingyuezhixing
时间:
2015-11-25 01:31
标题:
多线程玩玩IO流,求开导。。。
问题在最后面高手可以直接跳,我先从过程说起吧。
IO流快要块要学完,今天刚好看到文件切割,就想切割大一点的电影来玩玩,嗯嗯。刚好把多线程搬出来玩玩,看我飞起来有多快,
不多说,先来个分析设计:
*
* 要求:用最快的速度把一部电影按每段50M大小切割并存入C盘下。
*
* 思路:
* 1,建立5条读取流,每条读取流对应一个线程。
* 2,在每读取流建立五条打印流。
*
* 做法:
* 主线程:
* 1,获取文件大小。
* 2,以250M大小给文件分段,每段开启一个线程并非对应一个读取流。
* 3,当达到五个线程时,不再分配文件。
* 4,当出现一个线程的读取流读完所分配的文件时,在继续给其分配文件。直到把源文件分配完
*
* 读取流线程: (1读取 --2写入 )
* 0---50---100---150---200---249--
* 每段读取10M,同时就开启一个A写入流线程。并跳到下一段,读取10M,在开启B写入流。
*
* 如果A写入流完成,判断是否有下一段可读,有读下一段,没有则Await
* 再跳到下一段读取10M,如果A或Bwait则,唤醒并开始写入,
*
* 写入写入线程:
*
*
*/
感觉不是很难吗,
开写
-------
-------
...
---
--。。。。
-。。
。。。。。
。
哇卡,怎么从文件指定的字节流处开始读取,查文档,肯定有,,File类 ...没?!!什么情况,既然还没有子类,炸了吧
既然是读取那找一下读取流,找..找..找..PipedInputStream类,好像有点相关,但还没有真正我想要的。
好吧,看来我是找不到了,
那我就先写我先得到的部分吧,以后再把不足的补上,
继续开工。
一个读取流为一个对象,对应n个打印流线程,
写写写代码就出啦,
输出流:
package com.inout;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
public class OutputStreamTread implements Runnable {
private File file;
private ArrayList<byte[]> list;
private int beginof;
private int endof;
OutputStreamTread(File file ,ArrayList<byte[]> list , int beginof , int endof){
this.file = file;
this.list= list;
this.beginof =beginof;
this.endof= endof;
}
public void run() {
// while(true){
try {
BufferedOutputStream bufo =
new BufferedOutputStream(new FileOutputStream(file));
int begin = beginof ;
while(beginof<endof){
bufo.write(list.get(beginof));
beginof++;
bufo.flush();
}
while(begin<endof){
endof--; //释放内存空间,为了避免多线带来的安全问题,采用从最后位,往前擦出。
list.set(endof, null);
}
bufo.close();
}
catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
// }
//如果没有下一个可以输出的了,则 wait
}
// private byte[] nextBytes() {
// return it.next();
// }
}
打印流也来了
package com.inout;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
public class IntputStreamTread implements Runnable {
private File file;
private int count=1;
IntputStreamTread(File file){
this.file = file ;
}
ArrayList<byte[]> arby = new ArrayList<byte[]>();
public void run() {
// while(true){
try {
BufferedInputStream bufi =
new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[1024*1024]; //每次读取的长度,
int len = 0 ;
int index = 0 ;
int beginof =0;
int endof = 0 ;
int count = 0; //循环次数。
int maxcount = 5; //最大循环写入次数后,开启下一个输出流,既:切割的文件大小为 b.length * maxcoutn
int maxsize = 20; //集合最大长度。 最终集合的中大小为 b.length*maxsize
while((len=bufi.read(b))!=-1){
//如果集合未达到最大长度,就往集合中添加。
if(arby.size()<maxsize){
arby.add(new String(b,0,len).getBytes());
count++;
}
//否则,把集合作为循环数组使用。
else{
System.out.println("begiof--"+beginof);
if(index%maxcount==0){
System.out.println("index--"+index);
if(index>=arby.size()) //防止角标越界
index=0;
beginof=index; //寻找,满足条件的起始位置,
while(arby.get(beginof)!=null){
System.out.println(arby.get(beginof));
index=index+maxcount;
if(index>=arby.size()){
index=0;
}
beginof=index;
Thread.yield(); //不急,慢慢找,都用其他线程执行完就有了。
}
arby.set(index, new String(b,0,len).getBytes());
index++;
count++;
}
else{
arby.set(index, new String(b,0,len).getBytes());
index=index+1;
count++;
}
}
if(!((count)<maxcount)){
endof=beginof+count;
Thread th = getOutputThread(beginof ,endof);
beginof = endof ;
th.start();
count = 0;
continue;
}
}
if(count>0){
System.out.println(count+"-----");
endof=beginof+count;
Thread th = getOutputThread(beginof ,endof);
th.start();
}
bufi.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
// }
}
private Thread getOutputThread(int beginof , int endof) {
Thread th =
new Thread(new OutputStreamTread(new File("G:\\"+count+".part"), arby,beginof ,endof ));
System.out.println(count);
count++;
return th;
}
}
好长,经常角标越界,差点吐血,哭着3也得笑着说还好双十一放血太多吗》
主类就很简单了,
package com.inout;
import java.io.File;
public class TestMain {
public static void main(String[] args) {
File infile = new File("G:\\ab.jpg");
// File infile = new File("G:\\abc.txt");
Thread inth = new Thread(new IntputStreamTread(infile));
inth.start();
}
}
电脑抽风了还是自己抽风了,字体一会儿大,一会儿小,反正我也是醉了
回归正题,
测试方便,写几个文本数据吧?
测试一:
action ———— - - —— 角标越界。
测试二:
action —————— -- 少了两个(字符)字节
......
.....
测试N:
action————————哈哈完美了吧
————————————————————————
来个电影开切:
吓~!这速度,比复制快多了,这什么这么6
属性看一下应为也是没问题的,点--属性
疯了吧,少了50多个字节!!?
我试验是切文本没问题呀
再进行几次测试下,还是对文本就可以,对电影图片就不行。
再检查,检查...检查....
我靠,他妈的哪里有问题,老天耍我的吧!!砸电脑了、/、、
、
、
、
求开导!!
作者:
hdhunter
时间:
2015-11-25 10:54
代码格式太乱,看不清楚。待会再看。
作者:
lingyuezhixing
时间:
2015-11-25 12:18
hdhunter 发表于 2015-11-25 10:54
代码格式太乱,看不清楚。待会再看。
复制到eclipse上就清楚了,
如果还是不清楚,那就别去浪费时间了
作者:
萧未然
时间:
2015-11-27 23:35
明天看看,感觉毕老师讲的时候没这么复杂的
作者:
lingyuezhixing
时间:
2015-11-28 20:41
我兴趣的学友可以转到我的下一个贴,接着本帖进一步讨论
http://bbs.itheima.com/thread-264111-1-1.html
作者:
梦想家Eva
时间:
2015-12-7 00:36
好难啊!!!
作者:
5个半柠檬c
时间:
2015-12-9 00:43
其实你可以直接说下思路 或者你自己敲的哪些代码感觉有点错误的放出来,,,
作者:
sunpeijie
时间:
2015-12-19 14:38
文件切割肯定会破坏数据,我切割的视频图片也不能看,但是在把切割的整合了 就完整了
作者:
胆小的狙击手
时间:
2016-1-6 22:50
我提供一个思路:要只想开启五个线程完成这个文件切割的任务,我建议你可以开启一个只有五个线程的线程池,然后分割文件,定义一个字节数组根据要切割的大小来,比如说3M就是3*1024*1024。
定义一个变量记录长度,只要长度不大于文件的大小就说明没有切割完,然后一直不停的让线程池执行任务就行了,我还没有试过这个方法行不行,这是我的思路,我明天试试再给你回复,往采纳
作者:
wljr339
时间:
2016-1-13 22:22
本帖最后由 wljr339 于 2016-1-13 22:25 编辑
嗯嗯 其实吧 我学的也不是太好 但是我特别喜欢研究 因为IO流刚学一半 字符流 不能拷贝非文本文档 电影和图片都打不开 或者是看不了 要想复制只能用字节流 希望对你有帮助
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2