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

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

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

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

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

       出现问题:

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

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

第二种方案:

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

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



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




  
  
  1. /**
  2. * 从abc三个文件中向d中写
  3. * 多个线程向内存数组中读,读完之后,由单独的一个线程写入到文件中
  4. */
  5. public class Main042{
  6. //创建堵塞队列,用于读线程的数据存放
  7. public static BlockingQueue< byte[]> queue = new ArrayBlockingQueue<>( 1024* 1024);
  8. //创建 CountDownLatch,标记读线程的状态(是否读取完成)。
  9. public static CountDownLatch count = new CountDownLatch( 3);
  10. public static void main(String[] args){
  11. Read r1= new Read( "d:/a.txt",queue,count);
  12. Read r2= new Read( "d:/b.txt",queue,count);
  13. Read r3= new Read( "d:/c.txt",queue,count);
  14. Write w1 = new Write( "d:/d.txt", queue, count);
  15. r1.start();
  16. r2.start();
  17. r3.start();
  18. w1.start();
  19. }
  20. }
  21. class Write extends Thread{
  22. private BlockingQueue< byte[]> buffer;
  23. private FileOutputStream fileOutputStream;
  24. private CountDownLatch count;
  25. public Write(String file,BlockingQueue<byte[]> buffer,CountDownLatch count) {
  26. this.buffer = buffer;
  27. this.count =count;
  28. try {
  29. this.fileOutputStream = new FileOutputStream(file);
  30. } catch (FileNotFoundException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. public void run(){
  35. boolean b = true;
  36. while(b) {
  37. try {
  38. fileOutputStream.write(buffer.take());
  39. } catch (Exception e) {
  40. e.printStackTrace();
  41. }
  42. if(buffer.isEmpty()&&count.getCount()== 0) {
  43. //当缓冲区没有元素,并且 count为0,则说明读写完成
  44. b = false;
  45. }
  46. }
  47. }
  48. }
  49. //读线程
  50. class Read extends Thread{
  51. private BlockingQueue< byte[]> buffer;
  52. private FileInputStream fileInputStream;
  53. private CountDownLatch count;
  54. private volatile int i= 0;
  55. public Read(String readFileName, BlockingQueue<byte[]> buffer,CountDownLatch count) {
  56. this.count = count;
  57. this.buffer = buffer;
  58. try {
  59. this.fileInputStream = new FileInputStream(readFileName);
  60. } catch (FileNotFoundException e) {
  61. e.printStackTrace();
  62. }
  63. }
  64. public void run(){
  65. try {
  66. byte[] b = new byte[ 1024* 10];
  67. while((i = fileInputStream.read(b))>= 0) {
  68. buffer.put(Arrays.copyOf(b, i));
  69. }
  70. } catch (Exception e) {
  71. e.printStackTrace();
  72. } finally {
  73. count.countDown(); //读线程结束,count--;
  74. }
  75. }
  76. }




  
  

转载:https://blog.csdn.net/c_wangbin/article/details/77834409

猜你喜欢

转载自blog.csdn.net/q1054261752/article/details/88371880