多线程写多个文件

问题描述

我想实现一个多线程写入多个文件的程序.每个线程创建一个写入对象进行写入.比如创建从1到100为文件名的文件,每个文件写入一个数字,但是在写入中会有文件丢失的现象,最后不够100个文件.不太明白为什么会出现这个情况.同样的代码用来读多个文件将结果存入list中就没有问题.具体代码如下.忘各位大牛指教.importjava.io.BufferedWriter;importjava.io.File;importjava.io.FileWriter;importjava.io.IOException;importjava.util.concurrent.*;publicclassMutiWriter{publicstaticfinalintthreadSize=4;publicvolatilebooleanrunning=false;publicThread[]pool;publicBlockingQueue<Integer>producer=newLinkedBlockingQueue<Integer>();publicStringpath;publicintindex=1;publicMutiWriter(){this(threadSize);}publicMutiWriter(intsize){pool=newThread[size];Writerwriter=newWriter();for(inti=0;i<size;i++){pool[i]=newThread(writer,"thread"+i);pool[i].start();}running=true;}privateclassWriterimplementsRunnable{publicvoidrun(){inttemp=0;try{while((temp=producer.take())!=0){doWork(temp);}}catch(InterruptedExceptione){e.printStackTrace();}try{producer.put(0);}catch(InterruptedExceptione){e.printStackTrace();}}publicvoiddoWork(intnum){//System.out.println("ThreadNow"+Thread.currentThread().getName());try{BufferedWriterout=newBufferedWriter(newFileWriter(path+index+".txt"));out.write(String.valueOf(num));out.flush();out.close();System.out.println(index);}catch(IOExceptione){e.printStackTrace();}index++;}}publicvoidaddProducer(intnum){for(inti=1;i<num;i++){try{producer.put(i);}catch(InterruptedExceptione){e.printStackTrace();}}}publicvoidshutdown(){if(running){running=false;}try{producer.put(0);}catch(InterruptedExceptione){e.printStackTrace();}}publicvoidwaitting(){if(running||!producer.contains(0)){thrownewIllegalStateException("shutdownfirst");}try{producer.put(0);}catch(InterruptedExceptione1){e1.printStackTrace();}for(Threadt:pool){try{t.join();}catch(InterruptedExceptione){e.printStackTrace();}}}publicstaticvoidmain(String[]args){MutiWriterinstance=newMutiWriter(threadSize);instance.addProducer(101);instance.shutdown();instance.waitting();}}

解决方案

解决方案二:
这是一个典型的多线程同步问题,因为对index共享资源做++操作没有同步导致的,改进代码如下:packagetestproject;importjava.io.BufferedWriter;importjava.io.File;importjava.io.FileWriter;importjava.io.IOException;importjava.util.concurrent.*;publicclassMutiWriter{publicstaticfinalintthreadSize=4;publicvolatilebooleanrunning=false;publicThread[]pool;publicBlockingQueue<Integer>producer=newLinkedBlockingQueue<Integer>();publicStringpath;publicintindex=1;publicMutiWriter(){this(threadSize);}publicMutiWriter(intsize){pool=newThread[size];Writerwriter=newWriter();for(inti=0;i<size;i++){pool[i]=newThread(writer,"thread"+i);pool[i].start();}running=true;}privateclassWriterimplementsRunnable{publicvoidrun(){inttemp=0;try{while((temp=producer.take())!=0){doWork(temp);}}catch(InterruptedExceptione){e.printStackTrace();}try{producer.put(0);}catch(InterruptedExceptione){e.printStackTrace();}}publicvoiddoWork(intnum){//System.out.println("ThreadNow"+Thread.currentThread().getName());try{BufferedWriterout=newBufferedWriter(newFileWriter(path+getIndex()+".txt"));out.write(String.valueOf(num));out.flush();out.close();System.out.println(index);}catch(IOExceptione){e.printStackTrace();}index++;}}//这里需要同步synchronizedintgetIndex(){intidx=this.index;this.index++;returnidx;}publicvoidaddProducer(intnum){for(inti=1;i<num;i++){try{producer.put(i);}catch(InterruptedExceptione){e.printStackTrace();}}}publicvoidshutdown(){if(running){running=false;}try{producer.put(0);}catch(InterruptedExceptione){e.printStackTrace();}}publicvoidwaitting(){if(running||!producer.contains(0)){thrownewIllegalStateException("shutdownfirst");}try{producer.put(0);}catch(InterruptedExceptione1){e1.printStackTrace();}for(Threadt:pool){try{t.join();}catch(InterruptedExceptione){e.printStackTrace();}}}publicstaticvoidmain(String[]args){MutiWriterinstance=newMutiWriter(threadSize);instance.addProducer(101);instance.shutdown();instance.waitting();}}

解决方案三:
没那么简单,问题很多,楼上的做法还是有问题
解决方案四:
把index变量换成AtomicInteger类型的即可然后取数据是index.get()+1换成index.incrementAndGet()
解决方案五:
io操作不是不可中断吗?应该多出来,怎么会少?
解决方案六:
主要问题出现在publicintindex=1;变量对多个线程共享有可能出现线程1访问的时候这个变量值是1,线程2访问的时候还是1,因为你线程执行并不是同步的1、可以象一楼说的那样给index加个同步,但是要把doWork中的index++去掉2、还可以给这个doWork加个synchronized修饰符(这个保证是有序的)
解决方案七:
改成这样就没问题了publicclassT{publicstaticfinalintTHREAD_SIZE=4;publicThread[]pool;publicBlockingQueue<Integer>producer=newLinkedBlockingQueue<Integer>();publicStringpath="D:/";publicintindex=1;publicT(){this(THREAD_SIZE);}publicT(intsize){pool=newThread[size];Writerwriter=newWriter();for(inti=0;i<size;i++){pool[i]=newThread(writer,"thread"+i);pool[i].start();}}privateclassWriterimplementsRunnable{publicvoidrun(){inttemp=0;try{while((temp=producer.take())!=0){doWork(temp);}producer.put(0);}catch(Exceptione){e.printStackTrace();}}publicvoiddoWork(intnum){BufferedWriterout=null;try{out=newBufferedWriter(newFileWriter(path+num+".txt"));out.write(String.valueOf(num));out.flush();System.out.println(num);}catch(IOExceptione){e.printStackTrace();}finally{if(null!=out){try{out.close();}catch(IOExceptione){e.printStackTrace();}}}}}publicvoidaddProducer(intnum)throwsException{for(inti=1;i<=num;i++){producer.put(i);}producer.put(0);}publicstaticvoidmain(String[]args)throwsException{Tinstance=newT(THREAD_SIZE);instance.addProducer(100);}}

时间: 2024-12-21 17:09:13

多线程写多个文件的相关文章

读写-VS2003 多线程写INI文件问题

问题描述 VS2003 多线程写INI文件问题 在VS2003中,使用多线程读写同一个INI文件时,当连续写一千次以上后,出现写不进去的情况,这可能是由什么原因造成的? 解决方案 如果你没加锁,可能冲突了,如果加了锁,要注意是否发生死锁 解决方案二: 我猜测,死锁什么的吧? 加一些调试信息,完后用windebug打印一下,getlasterror()看看也行 解决方案三: http://bbs.csdn.net/topics/100110401http://bbs.csdn.net/topics

日志系统中多线程写文件的问题

问题描述 大家好,我现在在写一个日志系统,因为我需要在另外的项目中使用这个日志系统,在项目中调用日志系统的输出日志功能时,需要把日志写到一个文件里面,因为项目中可能启动几十上百个线程,这样的话,就会出现很多线程都是向同一个文件里面写日志,考虑的性能和资源的前提下,有没有一个好的方案解决多个线程写文件的问题.在下考虑到的方法有:1,每次每个线程读写文件的时候,打开输入流,写完了以后关闭输出流.这样做的话每次都要打开关闭输出流,会不会很耗资源2,程序中使用一个集合保存需要写文件的输出流,当哪个线程需

多线程和单线程拷贝文件那个效率高

问题描述 多线程和单线程拷贝文件那个效率高 单线程拷贝一个文件和多线程拷贝一个文件,那个效率更高,求大神写个例子证明一下. 解决方案 我菜,不会写,现在下载都是多线程的吧,看资源就知道.... 解决方案二: 拷贝文件的瓶颈在io,而不是cpu,多线程没有任何优势,而且对于机械硬盘,多个拷贝会导致寻道造成的性能损失.固态磁盘两者查不多. 解决方案三: 一提到多线程一般大家的第一感觉就是可以提升程序性能,在实际的操作中往往遇到性能的问题,都尝试使用多线程来解决问题,但多线程程序并不是在任何情况下都能

mfc多线程一次读写文件

问题描述 mfc多线程一次读写文件 CFile file1; int i; void CflieopenDlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 file1.Open(_T("D://vls//2.txt"),CFile::modeReadWrite); DWORD threadID; for(i = 0; i < 5; i++) { CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)T

csv-CFile写数据到文件中的问题

问题描述 CFile写数据到文件中的问题 使用CFile读写文件,将计算的多个类型结果(有long .int.cstring.double)输入到文本中的一行内,并用","隔开,形成csv格式.例如结果是:文件名:aaa.xxx,eee A:12% B:15% C:35%,D:38%,请教怎么写入文本.难道非要转换格式再输入,就不能像fwite一样一次写入文件中,aaa.xxx A:12% B:15% C:35,D:38%而且还要采用seekend()追加的方式进行吗 解决方案 你要的

制作网页时是先准备CSS文件还是先写好HTML文件?

css|网页 CSS文件先准备 还是先写好HTML文件?网上有很多种答案:先写HTML后写CSS:先写CSS后写HTML:两者同时写. 我的准则是先写HTML打好基础,然后再写CSS进行表现的控制! 对于初学者我建议两者一起写,先写CSS或者先写HTML对于初学者都不是恰当得的方法. 如果让一个人编写代码,你告诉他先写HTML,写完后 HTML不能修改了,然后你写CSS,如果他可以写出来,那这个人一定是一个水平非常高的Builder了!所以对于初学者,多数情况下我建议同时编写,具体我说一下步骤:

ie11-通过写注册表文件将某个网站加入到兼容性视图中

问题描述 通过写注册表文件将某个网站加入到兼容性视图中 例如:添加信任站点可以这样设置:(IP) [HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionInternet SettingsZoneMapRangesRange113240226136] "http"=dword:00000002 ":Range"="113.240.226.136",通过想用同样的办法将该网站加入到兼容性视图网

在linux内核添加自己写的头文件编译失败

问题描述 在linux内核添加自己写的头文件编译失败 我把一个自己编写的函数放在了自己写的en_decrypt_fun.h头文件中,这个头文件放在了/fs/yaffs2目录下面,现在想在/drivers/mmc/core/sd.c文件中调用这个自己写的函数,然后我就在这个C文件中写了一个include "/fs/yaffs2/en_decrypt_fun.h,结果make的时候编译报错,找不到/fs/yaffs2/en_decrypt_fun.h这个目录或文件. 请问各位linux大神,我是应该

java-为什么这三段代码写出来的文件没有区别,求大神解答

问题描述 为什么这三段代码写出来的文件没有区别,求大神解答 File f=new File("d:/text1.txt"); FileOutputStream outfile=new FileOutputStream(f,true); try { for(int i='A';i<='Z';i++) outfile.write(i); outfile.write('t'); byte b[]="java程序设计".getBytes(); outfile.writ