2011-03-04 12 views
7

() mkdirs साथ समस्याओं का सामना करने के बाद और interwebs आसपास poking, मैं वहाँ mkdirs साथ धागा सुरक्षा के मुद्दों() हैं कि इंप्रेशन प्राप्त करें।जावा में थ्रेड सुरक्षित तरीके से mkdirs का उपयोग कैसे करें?

वहाँ निर्देशिका ठीक से बनाए जाते हैं जब यह संभव है एक से अधिक थ्रेड समान फ़ाइल संरचना बनाने की कोशिश कर रहा हो सकता है कि यह सुनिश्चित करने के लिए एक तरीका है?

धन्यवाद

(मेरे मामले में मैं एंड्रॉयड पर इस का उपयोग किया जाएगा)

+0

आप के लिए आप क्यों लगता है कि के रूप में संदर्भ प्रदान कर सके 'mkdirs()' सुरक्षित थ्रेड नहीं है? –

+0

क्या कोई विवरण ज्ञात है (जे 2 एसई और एंड्रॉइड के लिए) किस परिस्थिति में यह समस्या उच्च संभावना के साथ दिखाई देगी?सीपीयू कोर, धागे, ओएस, फाइल सिस्टम की संख्या? मैं परीक्षण उद्देश्यों के लिए इस समस्या को उठाने की कोशिश कर रहा हूं। – Robert

+0

@TedHopp लिंक मर चुका है? क्या आप फिर से लिंक कर सकते हैं या समझा सकते हैं कि यह क्या था? –

उत्तर

0

ठीक है, मैं जानता हूँ कि यह थोड़ी देर के लिए निष्क्रिय कर दिया गया है, लेकिन मैंने सोचा कि शायद वहाँ एक सरल उपाय था। लेख आपको प्रश्न पर टिप्पणी में लिंक किए गए संकेत मिलता है कि समस्या सिर्फ निर्देशिका नहीं बनाया जा रहा है लगता है। इसका समाधान यह था:

if (!f.mkdirs()) { 
    f.mkdirs(); 
} 

हालांकि, यह अक्षम लगता है और अभी भी समस्याएं हो सकती हैं। तो, ऐसा क्यों न करें:

while (!f.mkdirs()) {} 

सरल, लेकिन यह काम करता है।

संपादित करें: एक सा सोच के बाद, कि उदाहरण गुमनामी के अंतराल हो सकता है और धागा ताला कारण बन सकता है।

while (!f.mkdirs()) { Thread.yield(); } 
बेशक

, कि केवल सिफारिश की जाएगी यदि आप एक धागा है कि धागा ताला कारण बन सकता है, और जब तक यह एक उच्च प्राथमिकता स्थिति नहीं है में कर रहे हैं: तो, यह एक बेहतर विचार हो सकता है। बस इसे बाहर रखो।

+0

... और सच में, सच उम्मीद है कि इस एक स्थिति है जहाँ mkdirs() अनुमतियाँ मुद्दों या एक गलत स्वरूप निर्देशिका नाम की तरह असली कारणों से विफल हो जाता है में चला जाता है कभी नहीं। –

+0

@smackfu अच्छा बिंदु। शायद यह सबसे अच्छा होगा समय की एक निश्चित संख्या में प्रयास करने के लिए है, तो एक त्रुटि संदेश प्रदर्शित होगा। –

+0

मैं सटीक समस्या और दुर्भाग्य के ऊपर मेरे लिए काम किया कुछ भी नहीं हो रही थी, लेकिन इस काम किया 'जबकि (! Dir.mkdirs()) \t \t {\t \t \t \t अगर (dir.isDirectory()) \t \t \t { \t \t \t \t तोड़; \t \t \t} \t \t \t \t \t} ' –

2

एक संभव समाधान एक MkDirService (नीचे सचित्र) केवल एक उदाहरण की गारंटी देता है और उसके अपने सूत्र में चलाता है कि होगा। BlockingQueue का उपयोग करना।

पहले सेवा:

package mkdir; 

import java.io.File; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.LinkedBlockingQueue; 

public class MkDirService extends Thread { 

    private static MkDirService service; 
    private BlockingQueue<File> pendingDirs = new LinkedBlockingQueue<File>(); 
    private boolean run = true; 

    private MkDirService() { 
    } 

    public synchronized static MkDirService getService() { 
     if (service == null) { 
      service = new MkDirService(); 
      new Thread(service).start(); 
     } 
     return service; 
    } 

    public void makeDir(File dir) { 
     pendingDirs.add(dir); 
    } 

    public void shutdown() { 
     run = false; 
    } 

    @Override 
    public void run() { 
     while (run || !pendingDirs.isEmpty()) { 
      File curDir = null; 
      try { 
       curDir = pendingDirs.take(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      if (curDir != null && !curDir.exists()) { 
       curDir.mkdir(); 
       System.out.println("Made: " + curDir.getAbsolutePath()); 
      } 
     } 
    } 
} 

टेस्ट:

package mkdir; 

import java.io.File; 

public class MkDirServiceTest { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     MkDirService mdServ = MkDirService.getService(); 
     mdServ.makeDir(new File("test1")); 
     mdServ.makeDir(new File("test1/test2")); 
     mdServ.makeDir(new File("test1/test3")); 
     mdServ.shutdown(); 

    } 
} 
+1

मैं अपने उदाहरण के लिए किसी भी सुधार का स्वागत करेंगे, मुझे यकीन है कि वहाँ कुछ बेहतर तरीके यह करने के लिए कर रहे हैं हूँ, और यह एक महान सीखने का अवसर पर विचार करेंगे। – bconneen

3

एक कार्यकर्ता धागा है कि सब कुछ को धारावाहिक में अपने सभी निर्देशिका निर्माण करते हैं। आप इसे आसान Runnables कि आपके कार्यकर्ता धागा करने के लिए mkdirs फोन पोस्ट करने के लिए बनाने के लिए एक Looper और एक Handler उपयोग कर सकते हैं। जब आप निर्देशिका बनाते हैं, तो आप अंतिम पोस्ट Runnable को संसाधित करने के बाद थ्रेड को समाप्त करने के लिए Looper.quit() को कॉल कर सकते हैं। documentation for Looper में नमूना कोड है जो दर्शाता है कि यह कितना छोटा है।

private static Lock fsLock = new ReentrantLock(); 

private void mkdir(File dir) throws FileNotFoundException { 

    if(dir.exists()) { 
     return; 
    } 

    fsLock.lock(); 
    try { 
     if(!dir.exists()) { 
      log.info("Creating directory {}", dir.getAbsolutePath()); 
      if(!dir.mkdirs()) { 
       throw new FileNotFoundException("Can't create directory " + dir.getAbsolutePath()); 
      } 
     } 
    } finally { 
     fsLock.unlock(); 
    } 
} 

विधि जल्दी यदि निर्देशिका पहले से मौजूद रिटर्न:

5

मुझे यकीन है कि अगर एंड्रॉयड समवर्ती पैकेज का समर्थन करता है, लेकिन यहाँ मेरी ले है नहीं कर रहा हूँ। यदि यह अस्तित्व में नहीं है, तो केवल एक धागा इसे बनाने का प्रयास करेगा।

+0

यह बहुत अच्छा है। यह मेरी समस्या को ठीक करता है, जिसमें एक ही निर्देशिका बनाने के प्रयास में मल्टीपल थ्रेड थे। एंड्रॉइड पर नहीं बल्कि नियमित जावा 5 एप्लिकेशन में। – Melloware

+0

हां, यह दिखने से कठिन है। –

1

Eaven यदि इस सूत्र थोड़ा पुराने मुझे आश्चर्य है कि वहाँ निम्नलिखित समाधान के साथ somethink गलत है अगर है:

package service; 

import java.io.File; 

public class FileService { 

    public static synchronized boolean mkdirs(File dir) { 
     return dir.mkdirs(); 
    } 
} 
संबंधित मुद्दे