2012-03-01 19 views
6

मैं कुछ फाइलों को एक फाइल में लिखना चाहता हूं। इसलिए, मैंने BufferedWriter कक्षा का उपयोग किया। चूंकि कई धागे उस फ़ाइल को लिखते हैं, इसलिए मैं जानना चाहता हूं कि और लिखने के लिए विधियां परमाणु हैं या नहीं।लेखक एक परमाणु विधि है?

इसके अलावा, मैं चाहता हूं कि प्रोग्राम एकाधिक फ़ाइलों में आउटपुट लिखने के लिए, और प्रति फ़ाइल 100 लाइनें (file.txt0, file.txt1, ... कहें)। उदाहरण के लिए

public class Main { 
    static ExecutorService exec = Executors.newFixedThreadPool(5); 
    BufferedWriter bw; 
    public class myWriter implements Runnable { 
     String str; 
     myWriter (String str) { 
      this.str = str; 
     } 
     public void run() { 
      bw.write(str); 
      bw.writeLine(); 
     } 
    } 
    public static void main(String[] args) { 
     bw = new BufferedWriter(new FileWriter("train.txt")); 
     for (String arg: args) 
      exec.execute(new myWriter(arg)); 
     exec.awaitTermination(100000, TimeUnit.MILLISECONDS); 
    } 
} 

क्या कोई मेरी मदद कर सकता है? अगर वे परमाणु नहीं हैं, तो मैं उन्हें परमाणु कैसे बना सकता हूं और टकराव से बच सकता हूं?

उत्तर

6

नहीं, वे परमाणु नहीं हैं।

यदि आप एक ही फ़ाइल में बहुभाषी लिखना चाहते हैं, तो FileLocks का उपयोग करें।

try { 
    // Get a file channel for the file 
    File file = new File("filename"); 
    FileChannel channel = new RandomAccessFile(file, "rw").getChannel(); 

    // Use the file channel to create a lock on the file. 
    // This method blocks until it can retrieve the lock. 
    FileLock lock = channel.lock(); 

    // Try acquiring the lock without blocking. This method returns 
    // null or throws an exception if the file is already locked. 
    try { 
     lock = channel.tryLock(); 
    } catch (OverlappingFileLockException e) { 
     // File is already locked in this thread or virtual machine 
    } 

    // Release the lock 
    lock.release(); 

    // Close the file 
    channel.close(); 
} catch (Exception e) { 
} 
+2

+1। जानकार अच्छा लगा। – Mudassir

+0

अच्छा काम। अगर मैं इसे कई फाइलों में आउटपुट लिखना चाहता हूं, प्रति फ़ाइल 100 लाइनें, मैं क्या कर सकता हूं? – orezvani

+0

@emab, यह निर्भर करता है। आपको अपने प्रश्न को और सटीक विवरण के साथ संपादित करना होगा कि आप वास्तव में क्या करना चाहते हैं (: – Marcelo

3

आप FileLocks उपयोग कर सकते हैं लेकिन वहाँ महंगा हो सकता है।

व्यक्तिगत रूप से, मैं एक सामान्य ऑब्जेक्ट लॉक का उपयोग करता हूं। जैसे

synchronized(bufferedWriter) { 
    bufferedWriter.write stuff 
    bufferedWriter.write more stuff 
} 
+0

परीक्षण करने के लिए लेकिन यहाँ bufferedWriter अंतिम होना चाहिए। मेरे bufferedWriter अंतिम नहीं है, क्योंकि यह एक नई फ़ाइल को खोलता है उत्पादन के हर 100 लाइन। – orezvani

+0

उस मामले में आप एक वस्तु जो 'final' जो आप उपयोग कर सकते हैं। यह वह जगह है जरूरत फ़ाइल के किसी भी पुन: खोलने के लिए भी लॉक करना चाहिए। –

5

नीचे कोड, यह BufferedWriter में लिखने के कार्यान्वयन है वहाँ समारोह शरीर में एक synchronized है कारण है, मुझे लगता है कि BufferedWriter में write() धागा सुरक्षित है jdk6 से स्रोत कोड है। बीटीडब्ल्यू, write(String)write(String,int,int) पर कॉल करके कार्यान्वित किया गया है।

public void write(String s, int off, int len) throws IOException { 

    synchronized (lock) { 

     ensureOpen(); 

     int b = off, t = off + len; 

     while (b < t) { 

      int d = min(nChars - nextChar, t - b); 
      s.getChars(b, b + d, cb, nextChar); 
      b += d; 
      nextChar += d; 

      if (nextChar >= nChars) 
       flushBuffer(); 
      } 
     } 
    } 
} 
+0

इससे प्रत्येक परमाणु लिखता है, लेकिन 'bw.write (str) को कॉल करते समय ओपी के कोड में अभी भी एक सहमति समस्या होती है; bw.writeLine(); '। – assylias

+0

@assylias यह एकमात्र मुद्दा नहीं है - flushToBuffer फ़ाइल को लिखने के समाप्त होता है। तो यदि एक समवर्ती धागा फ़ाइल को पढ़ना था, तो यह आंशिक डेटा पढ़ सकता था। – user1706991

1

NGloom, सही है निम्नलिखित एक प्रोग्राम है जो BufferredWriter.append() विधि (Oracle JDK 7 क्रम) जो विधि शरीर पर कोई समन्वयन का उपयोग करता है करने के लिए समवर्ती पहुँच करता है के एक भाग के एक धागा डंप है। यह बहुत स्पष्ट है कि BufferredWriter.append() का कार्यान्वयन BufferredWriter ऑब्जेक्ट के उदाहरण पर मॉनिटर का उपयोग करता है, इसलिए यह थ्रेड सुरक्षित है। हालांकि मुझे थ्रेड सुरक्षा on the related java doc के बारे में कुछ भी नहीं मिला है और इस प्रकार एपीआई ऐसी कोई गारंटी नहीं देता है, क्योंकि इस तरह के कार्यान्वयन अलग-अलग हो सकते हैं? इसके अलावा तथ्य यह है कि Writer.write() थ्रेड सुरक्षित है जो किसी अन्य लेखक को नहीं रोकता है जो एक अलग फ़ाइल को अलग-अलग OutputStream ऑब्जेक्ट को उसी फ़ाइल में लिखने के लिए एक साथ लिखने का प्रयास करता है, जो सुरक्षित नहीं है।

ForkJoinPool-1-worker-3" daemon prio=10 tid=0x00007f358c002800 nid=0x3e66 waiting for monitor entry [0x00007f360bdfb000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at java.io.BufferedWriter.write(BufferedWriter.java:220) 
    - waiting to lock <0x0000000760da06d8> (a java.io.OutputStreamWriter) 
    at java.io.Writer.write(Writer.java:157) 
    at java.io.Writer.append(Writer.java:227) 
    at ... 


ForkJoinPool-1-worker-2" daemon prio=10 tid=0x00007f358c001000 nid=0x3e65 waiting for monitor entry [0x00007f360befc000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at java.io.BufferedWriter.write(BufferedWriter.java:220) 
    - waiting to lock <0x0000000760da06d8> (a java.io.OutputStreamWriter) 
    at java.io.Writer.write(Writer.java:157) 
    at java.io.Writer.append(Writer.java:227) 
    at ... 
1

हाँ, BufferedWriter थ्रेड सुरक्षित है। नीचे स्निपेट देखें। सामग्री सिंक्रनाइज़ ब्लॉक लिखते समय थ्रेड सुरक्षा सुनिश्चित करता है।

public void write(int c) throws IOException { 
    synchronized (lock) { 
     ensureOpen(); 
     if (nextChar >= nChars) 
      flushBuffer(); 
     cb[nextChar++] = (char) c; 
    } 
} 

enter image description here

संबंधित मुद्दे