2015-07-09 12 views
8

मैं सूची कैश्ड है लौटने के लिए, मेरे कोड इसजावा कैश्ड वस्तु पुराने मूल्य

public class MyList { 
private final List<String> cache = new ArrayList<String>(); 

private List<String> loadMyList() { 
    // HEAVY OPERATION TO LOAD DATA 
} 

public List<String> list() { 
    synchronized (cache) { 
     if(cache.size() == 0) { 
      cache.addAll(loadMyList()); 
     } 
     return Collections.unmodifiableList(cache); 
    } 
} 

public void invalidateCache() { 
    synchronized (cache) { 
     cache.clear(); 
    } 
} 
} 

तरह लग रहा है क्योंकि सूची लोड बहुत भारी मैं एक अनुरोध मिला है कि अगर सूची लोड प्रगति पर है मैं वापस "पुराने" कैश्ड है डेटा ...

कि संभव है, और कोई मुझे कैसे यहां से आगे बढ़ने के लिए पर संकेत दे सकते हैं

संपादित करें: एडम होर्वाथ और bayou.io इस

की तरह कुछ sugested
public class MyList 
{ 
private final List<String> cache = new ArrayList<String>(); 
private final List<String> oldCache = new ArrayList<String>(); 
private volatile boolean loadInProgress = false; 

private List<String> loadMyList() 
{ 
    // HEAVY OPERATION TO LOAD DATA 
} 

public List<String> list() 
{ 
    synchronized (cache) 
    { 
     if(loadInProgress) 
      return Collections.unmodifiableList(oldCache); 
     else 
      return Collections.unmodifiableList(cache); 
    } 
} 

public void invalidateCache() 
{ 
    synchronized (cache) 
    { 
     // copy to old cache 
     oldCache = new ArrayList<String>(cache); 
     // set flag that load is in progress 
     loadInProgress = true; 
     // clear cache 
     cache.clear(); 

     // initialize load in new thread 
     Thread t = new Thread(new Runnable() 
     { 
      public void run() 
      { 
       cache.addAll(loadMyList()); 
       // set flag that load is finished 
       loadInProgress = false; 
      } 
     }); 
     t.start(); 


    } 

    } 
} 

क्या इस संपादित कोड में कोई समस्या है ?? जब से मैं बहु सूत्रण और/या अनुकूलन भुना में अनुभवी नहीं कर रहा हूँ मैं किसी भी और सभी प्रदर्शन संबंधी सुझाव देने

+5

मैं गलत नहीं कर रहा हूँ, तो आप [CopyOnWriteArrayList] (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html) – Pshemo

+0

मैं खोजे जा रहे मान लीजिए कि आपका मतलब है "कैश्ड" नहीं "कैश" –

+0

आपके उदाहरण में, 'सूची()' को कॉल करने वाले लोग आपकी सूची पर एक दृश्य प्राप्त करते हैं - इसका मतलब है कि जब आप सूची को साफ़/दोबारा तैयार करते हैं, तो कॉलर्स जिनके पास अभी भी उस दृश्य की प्रतिलिपि हो सकती है एक अस्थिर स्थिति में सूची देखें। क्या आप वाकई चाहते हैं? इसके अलावा आपके उदाहरण में कोई "पुराना" डेटा नहीं है - या तो सूची खाली है या इसे कुछ मिला है लेकिन इसे लोड होने के बाद इसे फिर से अपडेट नहीं किया गया है ... – assylias

उत्तर

2

"क्योंकि सूची लोड बहुत भारी मैं एक अनुरोध मिला है कि अगर सूची लोड प्रगति पर है मैं वापस है" पुराने "कैश्ड की सराहना करेंगे डेटा ... "

यह आपके" सिंक्रनाइज़ (कैश) "ब्लॉक के कारण नहीं होगा। आपको एक सूची बुलाने के लिए आपको अस्थिर बुलियन ध्वज (म्यूटेक्स) की आवश्यकता है। जब कोई थ्रेड सूची प्राप्त करने का प्रयास करता है() और म्यूटेक्स सत्य है, तो उसे कैश किया जाएगा। LoadMyList() पूरा होने पर इसे गलत सेट करें।

तो, सिंक्रनाइज़ किए गए ब्लॉक को हटाएं और अपनी सूची को एक अलग थ्रेड में लोड करना प्रारंभ करें।

public class MyList { 
    private List<String> cache = new ArrayList<String>(); 
    private volatile boolean loadInProgress = false; 

    private List<String> loadMyList() { 
     // HEAVY OPERATION TO LOAD DATA 
    } 

    public List<String> list() { 
     // Whatever is in cache, you can always return it 
     return Collections.unmodifiableList(cache); 
    } 

    /** 
    * Starts the loader-thread and then continues. 
    */ 
    public void invalidateCache() { 
     // Next two lines make sure only one Loader-thread can be started at the same time 
     synchronized (cache) { 
      if (!loadInProgress) { 
       // initialize load in new thread 
       Thread t = new Thread("Loader-thread") { 
        @Override 
        public void run() { 
         List<String> toAssign = loadMyList(); 
         // You can simply assign instead of copying 
         cache = toAssign; 
         // cache now "points to" refreshed list 
         loadInProgress = false; 
        } 
       }; 
       loadInProgress = true; 
       t.start(); 
       // Now let's exit the synchronized block. Hopefully the Thread will start working soon 
      } else { 
       // A Thread is already working or about to start working, don't bother him 
      } 
     } 
    } 
} 
+0

एक अलग स्थिति ध्वज खराब डिजाइन पसंद की तरह लगता है। ऐसे कई विकल्प हैं जहां आपको इसकी आवश्यकता नहीं है। (उदाहरण के लिए ऊपर Pshemos टिप्पणी देखें) – Keppil

+0

@ केपिल अच्छा विचार! लेकिन मुझे लगा है कि वह अपने कार्यान्वयन को ठीक करके थ्रेडिंग के बारे में जान सकता था। –

+0

@AdamHorvath मैंने अपना प्रश्न संपादित किया, क्या आपके मन में ऐसा कुछ था ?? – John

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