目的很简单,一个线程负责读取,另一个线程负责写入。每次读取指定大小的byte[],放到一个自己实现的队列中。简单的写了一下,如下:(读取线程)
public class GetThread implements Runnable
{
private Queue queue = null;
private int count = 0;
public GetThread(Queue queue, int count)
{
this.queue = queue;
this.count = count;
}
public void run()
{
FileInputStream fis = null;
try
{
fis = new FileInputStream("conf/source.txt");
}
catch(Exception e)
{}
try
{
byte[] buffer = new byte[1024];
while(fis.read(buffer) != -1)
{
synchronized(this.queue)
{
if(queue.getCount() < count) //队列有空间
{
queue.enqueue(buffer);
queue.notifyAll();
}
else
{
queue.wait();
}
}
buffer = new byte[512];
}
}
catch(Exception ex)
{}
finally
{
try
{
fis.close();
}
catch(IOException ie)
{}
}
}}(写入线程)
public class SetThread implements Runnable
{
private Queue queue = null;
public SetThread(Queue queue)
{
this.queue = queue;
}
public void run()
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream("conf/destination.txt"); while (true)
{
byte[] data = null;
synchronized (this.queue)
{
if (this.queue.getCount() == 0)
{
this.queue.wait();
}
data = (byte[]) queue.dequeue();
}
fos.write(data);
}
}
catch(Exception e)
{}
finally
{
try
{
fos.close();
}
catch(IOException ie)
{}
}
}
}主函数就不用帖出来了,就是初始化一个读取线程和写入线程,然后启动完事。问题是:如果待拷贝的文件不大,没有问题,但如果文件较大,就会出现只拷贝走一部分数据的情况,源数据文件中剩余的部分就不会被读取,确切说就是在 读取线程 的fis.read(buffer)部分出现问题(红色标注处),文件还没到头,但却返回-1,导致不会继续向Queue中放数据包。不知道是哪个步骤处有问题,诸位大虾帮下忙吧!谢谢啊^_^
public class GetThread implements Runnable
{
private Queue queue = null;
private int count = 0;
public GetThread(Queue queue, int count)
{
this.queue = queue;
this.count = count;
}
public void run()
{
FileInputStream fis = null;
try
{
fis = new FileInputStream("conf/source.txt");
}
catch(Exception e)
{}
try
{
byte[] buffer = new byte[1024];
while(fis.read(buffer) != -1)
{
synchronized(this.queue)
{
if(queue.getCount() < count) //队列有空间
{
queue.enqueue(buffer);
queue.notifyAll();
}
else
{
queue.wait();
}
}
buffer = new byte[512];
}
}
catch(Exception ex)
{}
finally
{
try
{
fis.close();
}
catch(IOException ie)
{}
}
}}(写入线程)
public class SetThread implements Runnable
{
private Queue queue = null;
public SetThread(Queue queue)
{
this.queue = queue;
}
public void run()
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream("conf/destination.txt"); while (true)
{
byte[] data = null;
synchronized (this.queue)
{
if (this.queue.getCount() == 0)
{
this.queue.wait();
}
data = (byte[]) queue.dequeue();
}
fos.write(data);
}
}
catch(Exception e)
{}
finally
{
try
{
fos.close();
}
catch(IOException ie)
{}
}
}
}主函数就不用帖出来了,就是初始化一个读取线程和写入线程,然后启动完事。问题是:如果待拷贝的文件不大,没有问题,但如果文件较大,就会出现只拷贝走一部分数据的情况,源数据文件中剩余的部分就不会被读取,确切说就是在 读取线程 的fis.read(buffer)部分出现问题(红色标注处),文件还没到头,但却返回-1,导致不会继续向Queue中放数据包。不知道是哪个步骤处有问题,诸位大虾帮下忙吧!谢谢啊^_^
一,把生产与消费分开,即,读的时候不能写,写的时候不能读,可以分别给它们一个状态,把它们都JOIN到一个主线程里来,用一个状态来区分,保证只有一种状态是活的即可。
二,当你想要读文件的时候,先把文件挪走或修改一个名子,然后再读,但是这种方法只有在WINDOWS下可行,因为WINDOWS会对文件做线程控制,如果有一个文件正在写或移,程序会报错,如果在其它平台上,系统不对它控制,程序就会出问题。
三,用队列的方式实现,一个入对,一个出对,入对文件名一定是写好的,消费者只能从队列中去取,但是这种方法不好,因为程序虽然是多线程的,但是过程是单线程的。
{
if (this.queue.getCount() == 0)
{
this.queue.wait();
}
data = (byte[]) queue.dequeue();
}
fos.write(data);
是不是写入线程少了唤醒啊?数据出队列以后难道你不唤醒读取线程继续读数据进队列吗?打算让读取线程读满队列后就一直wait吗?另:wait外尽量用循环,保证线程醒后能再次进过条件验证,而不是直接就去“做事”去了,也就是说上面的if语句有安全隐患!
对!这是两个问题。写文件后忘了notifyAll;结束条件。
但~问题是为什么程序运行后,不能将文件正确拷贝下来,只能拷贝一部分?数据文件稍微大点就这样(超过5k),在读文件的线程的fis.read(buffer)处,还没到文件尾部,就已经返回-1了?想不通啊
刚才将你代码修改后测试了N次(jdk1.5,windows xp),在我的环境中copy 5K,220K,13M的文件都没有问题。