多线程向一个文件中写数据

最近被问到Log4j如何通过多个线程向一个文件中写入数据,当时没有一点头绪, 因为用过windows记事本的小伙伴都知道,当一个记事本文件被同时打开多次,并且每个都修改,那么只会保留第一次打开的内容,这就是互斥锁的机制吧。 

具体场景:三个线程分别读取三个文件a,b,c 并向d文件中写入

现在想起来两个方案给小伙伴分享一下:

第一种(不可行)使用IO流复用,就是多个线程共用一个IO流

       出现问题:

              1.部分文件内容无法保存。

              2.影响其它线程使用文件

第二种方案:

思路:既然不能同时读写,那么就一个或多个线程读取文件,然后单独的一个或多个线程写文件。

比如 创建三个线程r1,r2,r3分别读取a,b,c  创建一个线程w1将内容写入到 d. 那么读写操作就可以同步进行,也不需要IO复用了,只需要创建一个缓冲区即可。



不多说了,上代码(因为需要代码尽量清晰,省略所有io.close())



/**
 * 从abc三个文件中向d中写
 * 多个线程向内存数组中读,读完之后,由单独的一个线程写入到文件中
 */
public class Main042{
	//创建堵塞队列,用于读线程的数据存放
	public static BlockingQueue<byte[]> queue = new ArrayBlockingQueue<>(1024*1024);
	//创建 CountDownLatch,标记读线程的状态(是否读取完成)。
	public static CountDownLatch count =new CountDownLatch(3);
	public static void main(String[] args){
		Read r1= new Read("d:/a.txt",queue,count);
		Read r2= new Read("d:/b.txt",queue,count);
		Read r3= new Read("d:/c.txt",queue,count);
		Write w1 = new Write("d:/d.txt", queue, count);
		r1.start();
		r2.start();
		r3.start();
		w1.start();
	}
	
}

class Write extends Thread{
	private BlockingQueue<byte[]> buffer;
	private FileOutputStream fileOutputStream;
	private CountDownLatch count;
	public Write(String file,BlockingQueue<byte[]> buffer,CountDownLatch count) {
		this.buffer = buffer;
		this.count =count;
		try {
			this.fileOutputStream = new FileOutputStream(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	public void run(){
		boolean b =true;
		while(b) {
			try {
				fileOutputStream.write(buffer.take());
			} catch (Exception e) {
				e.printStackTrace();
			}
			if(buffer.isEmpty()&&count.getCount()==0) {
				//当缓冲区没有元素,并且 count为0,则说明读写完成
					b =false;
			}
		}
		
	}
}
//读线程
class Read extends Thread{
	private BlockingQueue<byte[]> buffer;
	private FileInputStream fileInputStream;
	private CountDownLatch count;
	private volatile int i=0;
	
	public Read(String readFileName, BlockingQueue<byte[]> buffer,CountDownLatch count) {
		this.count = count;
		this.buffer = buffer;
		try {
			this.fileInputStream = new FileInputStream(readFileName);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	public void run(){
		try {
			byte[] b = new byte[1024*10];
			while((i = fileInputStream.read(b))>=0) {
					buffer.put(Arrays.copyOf(b, i));
				}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			count.countDown();//读线程结束,count--;
		}
	}
}





  • 11
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在Java中,可以使用多线程同一个文件写入数据。但是需要注意的是,多个线程同时写入同一个文件可能会导致数据错乱和文件损坏的问题。因此,在向同一个文件写入数据时,需要使用线程安全的方式。 以下是一个使用多线程同一个文件写入数据的例子: ```java import java.io.FileWriter; import java.io.IOException; public class FileWriterThread extends Thread { private FileWriter writer; public FileWriterThread(FileWriter writer) { this.writer = writer; } @Override public void run() { synchronized (writer) { // 使用 synchronized 关键字保证线程安全 try { writer.write(Thread.currentThread().getName() + ": Hello, World!\n"); System.out.println(Thread.currentThread().getName() + " 写入数据成功!"); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { FileWriter writer = null; try { writer = new FileWriter("test.txt", true); // true 表示追加写入 for (int i = 0; i < 10; i++) { new FileWriterThread(writer).start(); // 开启 10 个线程向同一个文件写入数据 } } catch (IOException e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } } ``` 在上面的例子中,我们创建了一个 `FileWriterThread` 类,它继承了 `Thread` 类,并覆盖了 `run()` 方法。在 `run()` 方法中,我们使用 `FileWriter` 类向文件写入数据,并使用 `synchronized` 关键字保证线程安全。 在 `main()` 方法中,我们创建了一个 `FileWriter` 对象,并开启了 10 个线程向同一个文件写入数据。由于我们使用了 `synchronized` 关键字,因此多个线程可以安全地向同一个文件写入数据。 需要注意的是,在使用 `FileWriter` 向文件写入数据时,需要使用 try-catch-finally 语句块来保证资源的正确释放。在上面的例子中,我们在 `finally` 中关闭了 `FileWriter` 对象。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值