October 27, 2012

Collections Utility Class 2

ပြီးခဲ့သော အခန်းတွင် Collections ကလပ်စ်အား အသုံးပြု၍ Collection Interface အား အသုံးပြုနိုင်သော အလဂိုရီဇင်အား လေ့လာခဲ့သည်။ ယခုတစ်ခေါက်တွင်လည်း Collections ၏ လုပ်ဆောင်ချက်များအား ဆက်လက်၍ ရေးသားသွားပါမည်။


ဖွဲ့စည်းပုံအား သိရှိနိုင်သော လုပ်ဆောင်ချက်များ

Collections ၏ frequency နှင့် disjoint အလဂိုရီဇင်များသည် Collection များ၏ ဖွဲ့စည်းပုံကို သိရှိနိုင်သော လုပ်ဆောင်ချက်များ ဖြစ်ကြသည်။ Collections#frequency သည် Collection တစ်ခုအတွင်း Object တစ်ခုသည် အကြိမ်မည်မျှပါဝင်သည်ကို သိရှိနိုင်မည် ဖြစ်သည်။ တဖန် disjoint လုပ်ဆောင်ချက်သည် Collection နှစ်ခု အတွင်း ပတ်သက်မှု့ ရှိမရှိ သိရှိနိုင်မည် ဖြစ်သည်။

FrequencySample.java
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class FreequencySample {

    static final String [] STRINGS = {"1","2","1","1","2","3","4","2","1"};
    public static void main(String[] args) {
        List<String> list = Arrays.asList(STRINGS);
        int count = Collections.frequency(list, "1");
        System.out.println("Frequency of 1 is " + count);
    }
}
အထက်ပါ နမှုနာအတိုင်း List Object တစ်ခုဖြစ်သော list အတွင်းတွင် "1" ဘယ်နှစ်ကြိမ်ပါသလဲ ဆိုတာကို စာကြောင်း ၁၀ တွင် ရေးသားထားသည့်အတိုင်း Collections.frequency လုပ်ဆောင်ချက်ဖြင့် သိရှိနိုင်ပါသည်။ ပဋ္ဌမ Argument မှာ ရှာဖွေမည့် List အား ရေးသားရမည် ဖြစ်ပြီး၊ ဒုတိယ Argument တွင် ရှာဖွေမည့် Object အား ရေးသားရမည် ဖြစ်ပါသည်။

DisjointSample.java
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class DisjointSample {

    static final String[] STRINGS1 = { "1", "2", "1", "1", "2", "3", "4", "2",
            "1" };
    static final String[] STRINGS2 = { "1", "2", "5" };
    static final String[] STRINGS3 = { "6", "7", "8" };

    public static void main(String[] args) {
        List<String> list1 = Arrays.asList(STRINGS1);
        List<String> list2 = Arrays.asList(STRINGS2);
        List<String> list3 = Arrays.asList(STRINGS3);

        System.out.println("List1 disjoint List2 : "
                + Collections.disjoint(list1, list2));
        
        System.out.println("List2 disjoint List3 : "
                + Collections.disjoint(list2, list3));
    }

}

လစ်တစ်ခုနှင့် တစ်ခု ပတ်သက်မှု့ရှိမရှိအား Collections#disjoint လုပ်ဆောင်ချက်ကို အသုံးပြုနိုင်ပါမည်။ အကယ်၍ လစ်နှစ်ခုအတွင်း တူညီသော Element အချို့ပါဝင်ချင်း မရှိပါက၊ ပတ်သက်မှု့ မရှိပါက true ကို ရရှိမည် ဖြစ်ပြီး၊ လစ်တစ်ခုအတွင်းပါဝင်သော အချို့သော Element များက အခြားလစ်တစ်ခုအတွင်း ပါဝင်ပါက false ကို ရရှိနိုင်မည် ဖြစ်သည်။ အထက်ပါ နမှုနာအား Run ကြည့်သောအခါ အောက်ပါအတိုင်း တွေ့ရှိရမည် ဖြစ်ပါသည်။




အသုံးများသော အခြားသော လုပ်ဆောင်ချက်များ

Collections Class အတွင်းတွင် အထက်ဖော်ပြပါ လုပ်ဆောင်ချက်များအပြင် အခြားသော အသုံးဝင်သော လုပ်ဆောင်ချက်များကို ပြင်ဆင်ထားပါသည်။

အမည် ရှင်းလင်းချက်
reverse Collectionအတွင်းရှိ Element များ၏ အစီအစဉ်အား ပြောင်းပြန် ပြန်ပြီး စီစဉ်ရာတွင် အသုံးပြုနိုင်သောလုပ်ဆောင်ချက် တစ်ခုဖြစ်ပါသည်။
fill List တစ်ခုအတွင်းရှိ Element များအား Object တစ်ခုဖြင့် အစားထိုးနိုင်၏။ ဤလုပ်ဆောင်ချက်သည် List တစ်ခုအား ပြန်လည် Initialize လုပ်ရာတွင် အသုံးဝင်မည် ဖြစ်ပါသည်။
copy List တစ်ခုမှ အခြားသော List တစ်ခုဆီသို့ ကော်ပီကူးရာတွင် အသုံးပြုနိုင်ပါသည်။ Argument အနေဖြင့်List နှစ်ခုကို လိုအပ်မည် ဖြစ်ပါသည်။ ကော်ပီ List နှင့် မှုရင်း List တို့ဖြစ်ကြ၏။ ကော်ပီ List ၏ size သည် အနည်းဆုံး မှုရင်း List လောက်ရှိရန် လိုအပ်ပါသည်။ မှုရင်း List ပမာနထက် ပိုများသွားပါက ပိုသော နေရာများအား အကျိုးသက်ရောက်မှု့ ရှိမည် မဟုတ်ပေ။
swap List တစ်ခုအတွင်းရှိ Element များအား နေရာပြောင်းရာတွင် အသုံးပြုနိုင်မည် ဖြစ်ပါသည်။ ပဋ္ဌမ Argument မှာ List Object ဖြစ်ပြီး၊ နောက် Argument နှစ်ခုမှာ ပြောင်းလိုသည့် နေရာ (index) များ ဖြစ်ကြသည်။ အကယ်၍ ပြောင်းရွှေ့လိုသော နေရာနှစ်ခုသည် List ၏ size ထက်များနေပါက IndexOutOfBoundException ကို ဖြစ်ပေါ်စေမည် ဖြစ်၏။
Colletions.swap (list, 0, 4) ဟု ရေးသားထားပါက list ၏ 0 နေရာရှိ Element နှင့် 4 နေရာရှိ Element တို့အား အသီးသီး နေရာပြောင်းပေးမည် ဖြစ်သည်။
["1","2","3","4","5"] ဟုရှိခဲ့ပါက swap လုပ်ပြီးသောအခါ ["5","2","3","4","1"] ဖြစ်သွားမည် ဖြစ်ပါသည်။
addAll addAll လုပ်ဆောင်ချက်သည် Collection တစ်ခုအတွင်းကို၊ ဒုတိယ Argument ဖြစ်သော Varargs အတွင်းမှ Object များအား တစ်ပြိုင်နက်တည်း ထည့်သွင်းနိုင်မည် ဖြစ်ပါသည်။ 
min Collectionအတွင်းရှိ သဘာဝအစီအစဉ် အတိုင်းစီစဉ်သောအခါ အကြီးမားဆုံး Element ကို ရရှိမည် ဖြစ်ပါသည်။
max Collection အတွင်းရှိ သဘာဝအစီအစဉ် အတိုင်း စီစဉ်သောအခါအသေးငယ်ဆုံး Element ကို ရရှိမည် ဖြစ်သည်။


အထူးအသုံးပြုပုံများ

အထက်ဖော်ပြပါ အသုံးပြုနည်းများမှာပုံမှန် ကော်လက်ရှင်များအား အသုံးပြုသော အသုံးပြုနည်းများဖြစ်ကြသည်။ သို့ရာတွင် Multi Thread Programming များတွင်၎င်း၊ Concurrency Framework များတွင်၎င်း၊ Parallel Processing များတွင်၎င်း အစရှိသည့် သီးခြားအခြေအနေများတွင် အသုံးပြုလိုသည့် အခါများလည်း ရှိတတ်ပေသည်။ ထိုအခါမျိုးတွင်ရိုးရိုး Collection များအား အသုံးပြု၍ မရနိုင်ပေ။ အဘယ်ကြောင့်ဆိုသော် Collection Framework အတွင်းရှိ General Purpose Implementations များသည် Thread Safe မဟုတ်သောကြောင့် ဖြစ်သည်။

Thread Safe ဆိုသည်မှာ Multi Thread များအကြားတွင် အသုံးပြုရာတွင် အမှားအယွင်းမရှိစေရန် ကာကွယ်ပေးထားခြင်း ဖြစ်၏။ ဒီလိုဆိုရင် ဘာလို့ Collection တွေအားလုံးမှာ Thread Safe မလုပ်ထားတာလဲ ဟု မေးစရာရှိပါလိမ့်မည်။ မလိုအပ်ပဲ Thread Safe လုပ်ထားပါက Synchronization အစရှိတဲ့ လေးလံတဲ့ အလုပ်များကို မလိုအပ်ပဲ လုပ်နေရမည် ဖြစ်သောကြောင့် ဖြစ်သည်။

အချို့သောသူများရှိပါသည်။ General Purpose Collection များအား ဘုမသိဘမသိ Multi Thread Program အတွင်းမှာ သွားသုံးပြီး Collection ဟာ Thread Safe မဟုတ်ဘူးဆိုပြီး ထအော်နေသူများရှိပါသည်။

Collections Utility Class တွင် အထက်ပါ အထူးအခြေအနေများတွင် အသုံးပြုနိုင်ရန် လုပ်ဆောင်ချက်များကိုလည်း ပြင်ဆင်ထားပါသည်။


Singleton

Singleton သည် Design Pattern တစ်မျိုးဖြစ်ပြီး၊ တစ်ခုထက်ပိုပြီး Instance ကို မရေးသား လိုသည့်အခါမျိုးတွင် အသုံးပြုလေ့ရှိ၏။ Collection Framework တွင်လည်း တစ်ခုတည်းသော Collection Instance များအား အသုံးပြုနိုင်ရန် Collections ကလပ်စ်တွင် ပံ့ပိုးပေးထားပါသည်။

public static <T> Set<T> singleton (T o)
public static <T> List<T> singletonList(T o)
public static <K,V> Map<K,V> singletonMap(K key, V value) 

လုပ်ဆောင်ချက်များ၏ အမည် အတိုင်း singleton သည် Object တစ်ခုသာပိုင်ဆိုင်သော Set အင်းစတန့်စ်အား ပြန်ပေးမည်ဖြစ်ပြီး၊ singletonList သည် List အင်းစတန့်စ်အား၎င်း၊ singletonMap သည် Map အင်းစတန့်စ် အား၎င်း ပြန်ပေးမည် ဖြစ်သည်။ singleton လုပ်ဆောင်ချက်များဖြင့် ပြုလုပ်ထားသော တောက်လျှောက် တစ်ခုတည်းသော အင်းစတန့်စ်အဖြစ် အသုံးပြုနိုင်မည် ဖြစ်သည်။ အကယ်၍ singleton ဖြင့် လုပ်ယူထားသော Collection ပြုပြင်ပြောင်းလည်း ကြည့်ပါက java.lang.UnsupportedOperationException အား ဖြစ်ပေါ်စေမည် ဖြစ်ပါသည်။

singleton လုပ်ဆောင်ချက်ဘယ်လိုနေရာတွေမှာ အသုံးဝင်သလဲ ဆိုတာ သိပ်ပြီး မသိ။ ဘာတွေကောင်းလဲ ဘယ်နေရာမှာ သုံးသင့်သလဲနမှုနာကို ရေးရင်းလေ့လာကြည့်ပါဦးမည်။

SingletonSample.java
iimport java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class SingletonSample {
    
    public static void main(String[] args) {
        
        final Set<String> set = new HashSet<>(Arrays.asList("Element"));
        Set<String> singleton = Collections.singleton("Element");
        
        System.out.println(set);
        System.out.println(singleton);
    }
}

Element တစ်ခုသာပိုင်၍ ပြောင်းလည်းမရနိုင်သော Set တစ်ခုကို လိုချင်ပါက အထက်ပါ စာကြောင်း ၁၀အတိုင်း final တတ်၍ရေသားနိုင်ပါသည်။ ဘာကြောင့် Singleton ကို လိုအပ်ရသနည်း။ ရုတ်တရက်ကြည့်လျှင် Arrays ဖြင့် List ကို ရယူ၍ HashSet တွင် အစားထိုးနေရသဖြင့် Step နည်းနည်းများများ ရေးရသည်ထက် ပိုပြီးထူးသည်ဟု မမြင်ပါ။ Eclipse Debug Mode ဖြင့် ၎င်း set နှင့် singleton တို့အား ကြည့်ကြည့်ပါမည်။

set အား ကြည့်ထားသော ပုံဖြစ်ပါသည်။
singleton အား ကြည့်ထားသော ပုံဖြင့်ပါသည်။

အထက်ပုံ နှစ်ခုအား ယှဉ်ကြည့်ပါက သိနိုင်မည် ဖြစ်ပါသည်။ set သည် အတွင်းပိုင်းတွင် နေရာ အများကြီးကို ယူထားရပါသည်။ သို့ရာတွင် singletone အတွင်းမှာမူ String element ဖြစ်သော အင်းစတန့်စ် တစ်ခုသာပိုင်ဆိုင်၏။ ပြုပြင်ပြောင်းလည်း၍မရနိုင်သော Element တစ်ခုတည်းသာပိုင်ဆိုင်သော Set ခြင်း တူသော်လည်း singleton သည် အလွန်ပေါ့ပါးသည်ဆိုသည်ကို တွေ့နိုင်မည် ဖြစ်သည်။

ဤနည်းအားဖြင့် Element တစ်ခုတည်းသာပိုင်၍ ပြောင်းလည်းမရနိုင်သော Set Object အားအသုံးပြုလိုပါက singleton အား အသုံးပြုခြင်းက ရိုးရိုး HashSet အား new လုပ်ခြင်းထက် ပို၍ Performance ကောင်းကြောင်း တွေးမြင်နိုင်မည် ဖြစ်ပါသည်။ 


Unmodifiable Collections

ပရိုဂရမ်များ ရေးသားရာတွင် ရေးရင်းရေရင်းရှုပ်ထွေးလာပါက ပရိုဂရမ်မာက မျှော်လင့်မထားသော အရာများ ဖြစ်ပေါ်လေ့ရှိ၏။ ရန်ဖန်ရံခါ အစပိုင်းတွင် လိုအပ်သော အချက်အလက်များအား တွက်ယူ၍ နောက်ပိုင်းတွင် ထိုအချက်အလက်များအား အကြိမ်ကြိမ်ခေါ်ယူ သုံးဆွဲလိုသည့် အခါမျိုးရှိ၏။ ထိုအချက်အလက်များအား ပြောင်းလည်း၍ မရအောင် လုပ်ထားလိုသည့် အခါမျိုးရှိ၏။ Collections တွင် ထိုအခါမျိုးတွင် အသုံးပြုနိုင်ရန် လုပ်ဆောင်ချက်များကို ပြင်ဆင်ထားပါသည်။

public static <T> Collection<T> unmodifiableCollection(Collection<T> c)
public static <T> List<T> unmodifiableList(List<T> list)
public static <K,V> Map<K,V> unmodifiableMap(Map<K,V> m)
public static <T> Set<T> unmodifiableSet(Set<T> s)
public static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K,V> m)
public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)

အထက်ပါ လုပ်ဆောင်ချက်များအား အသုံးပြုခြင်းအားဖြင့် Collection Instance များအား ပြုပြင်ပြောင်းလည်း၍ မရနိုင်အောင် ပြောင်းလည်းနိုင်ပါသည်။


စကားပို : Multithread Programming

အမှန်ဆို ဒီနေရာတွင် Synchronization နှင့် ပတ်သက်ပြီး မရေးလိုသေးပါ။ Multithread Programming နှင့် Parallel Programming အကြောင်း Concurrency Framework အကြောင်း ရေးရင်း Thread Safe နှင့် Synchronization အကြောင်းကို ရေးလိုပါသည်။ သို့ရာတွင် Collections အကြောင်း ရေးရင်း Synchronization အကြောင်း တစ်ခုတည်း ချန်မထားချင်သောကြောင့် အနည်းအကျဉ်း ထိတွေ့သွားပါမည်။

ကွန်ပျူတာပေါ်တွင်အပလီကေးရှင်းများအား အလုပ်လုပ်စေရာတွင် File ပေါ်တွင် သိမ်းဆည်းထားသော Commands နှင့် အချက်အလက်များအား Virtual Memory အပေါ်ခေါ်ယူ၍ အလုပ်လုပ်စေပြီး လိုအပ်သလို Hard Desk အပေါ်တွင် သိမ်းဆည်းထားသော Data များအား ဆက်သွယ် အသုံးပြုလေ့ရှိ၏။ ထိုကဲ့သို့ အပလီကေးရှင်း တစ်ခုအား အလုပ်လုပ်စေသည့် Unit အား Process ဟုခေါ်ဆိုပါသည်။
CPU ၏ အမြန်နှုန်းနှင့်စာလျှင် Hard Disk ပေါ်မှ အချက်အလက်များအား ခေါ်ယူသည့် Speed သည် အလွန်နောက်ကျလေ့ရှိ၏။ ထိုကဲ့သို့ စောင့်နေသောအချိန်အတွင်းတွင် အခြားသော အလုပ်များကို ခိုင်းစေထားခြင်းသည် လုပ်ဆောင်ချိန်ကို လျှင်မြန်စေမည် ဖြစ်သည်။ ဤနည်းအားဖြင့် Process တစ်ခု အလုပ်လုပ်နေစဉ် အခြားသော Process များအား ပြိုင်တူ အလုပ်လုပ်စေသော Parallel Processing ကို ပေါ်ပေါက်စေခဲ့ပါသည်။

Process သည် ပရိုဂရမ်တစ်ခုအား အလုပ်လုပ်စေရန် သီးခြား မံမိုရီဧရိယာကို ပိုင်ဆိုင်ပြီး တစ်ခုနှင့်တစ်ခု လွတ်လပ်စွာ အလုပ်လုပ်စေနိုင်သလို အခြားတစ်ဘက်မှာလည်း တစ်ခုစီ သီးခြား မံမိုရီကို ပေးထားရတဲ့အတွက် တစ်ခုနှင့်တစ်ခု ပြောင်းလည်းရာတွင် လေးလံတက်ပါသည်။ ထို့ကြောင့် အလုပ်များကို သီးခြားလုပ်နိုင်စေပြီး Memory နှင့် Data အစရှိသော Resource များအား ဘုံအနေဖြင့် အသုံးပြုနိုင်သော Thread များကို ဖန်တီးလာကြပါသည်။ ဤကဲ့သို့ Thread တစ်ခု အလုပ်လုပ်နေစဉ် အခြားသော Thread များကိုလည်း တပြိုင်တည်း အသုံးပြုနိုင်သော ပရိုဂရမ်မင်း နည်းပညာ ဖြစ်သော Multithread Programming ကို ပေါ်ပေါက်စေလာခဲ့ပါသည်။


Synchronization

Java သည်လည်း Multithread Programming အားပေါ်ပြီး မကြာခင်ကတည်းက ပံ့ပိုးပေးခဲ့ပါသည်။ Thread တစ်ခု အလုပ်လုပ်နေချိန်တွင် လေးလံသော အလုပ်အား အခြားသော Threadဖြင့်ခိုင်းထားပြီး ထို Thread အလုပ်ပြီးခါမှ အခြားသော Thread ဖြင့် ပူးပေါင်းဆောင်ရွက်စေခြင်း ဖြစ်သည်။ သို့ရာတွင် Object တစ်ခုအား Thread များမှ အပြိုင် Update လုပ်သည့်အခါမျိုး ရှိပေလိမ့်မည်။ ထိုအခါမျိုးတွင် Object အား အစီအစဉ်တကျ Update လုပ်စေရန် စီမံဖို့လိုအပ်ပါသည်။ ဤကဲ့သို့ စီမံခြင်းအား Synchronization ဟုခေါ်ဆိုပါသည်။

Collections ကလပ်စ်တွင် Synchronized Collection Object များအဖြစ် ပြောင်းလည်းပေးနိုင်သော လုပ်ဆောင်ချက်များအား ပြင်ဆင်ထားပါသည်။ ၎င်းတို့မှာ အောက်ပါအတိုင်းဖြစ်၏။

static <T> Collection <T> synchronizedCollection (Collection <T> c)
static <T> List <T> synchronizedList (List <T> list)
static <T> Set <T> synchronizedSet (Set <T> s)
static <K,V> Map <K,V> synchronizedMap (Map <K,V> m)
static <T> SortedSet <T> synchronizedSortedSet (SortedSet <T> s)
static <K,V> SortedMap <K,V> synchronizedSortedMap (SortedMap <K,V> m)

Thread တစ်ခုနှင့် တစ်ခုအကြားတွင် စနစ်တကျ အလုပ်မလုပ်စေသောအခါ မည်ကဲ့သို့ အစဉ်မပြေမှု့များကို ဖြစ်ပွားစေသနည်း။ လက်တွေ့ရေးသားကြည့်ပါမည်။

ThreadSafeSample1.java
import java.util.LinkedList;
import java.util.List;

public class ThreadSafeSample1 extends Thread{

    static int total = 0;
    private final List<?> list;
    
    public ThreadSafeSample1(List<?> list) {
        this.list = list;
    }
    
    @Override
    public void run() {
        int count = 0;
        while(list.remove(null))
            count++;
        
        System.out.println("Consume " + count + " Element");
        
        synchronized (this.getClass()) {
            total += count;
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        
        List<Thread> threads = new LinkedList<>();
        List<?> list = new LinkedList<>();

        for (int i=0; i < 100000; i++)
            list.add(null);
        
        for (int i=0; i < 5; i++)
            threads.add(new ThreadSafeSample2(list));
        
        for (Thread t : threads)
            t.start();
            
        for (Thread o : threads)
            o.join();

        System.out.println("Total is " + total);
    }
}
အထက်ပါ နမှုနာတွင် MultiThread အား အသုံးပြုနိုင်ရန် Threadကလပ်စ်အား Extends လုပ်ပြီး ရေးသား ထားပါသည်။ List တစ်ခုအား Constructor ဖြင့် ရယူပြီး Member Variable ဖြစ်သော list တွင် အစားထိုးပါသည်။ တဖန် Thread အနေဖြင့် အလုပ်လုပ်စေမည့် run လုပ်ဆောင်ချက်အား override လုပ်၍၊ list အတွင်းမှ null အား remove လုပ်စေပြီး count ဖြင့် အကြိမ်အား မှတ်သားထားစေပါသည်။ နောက်ဆုံးတွင် count အား System.out လုပ်စေပြီး၊ static variable ဖြစ်သော total တွင် ပေါင်း၍ အစားထိုးစေပါသည်။ ဤနည်းအားဖြင့် remove လုပ်သောအကြိမ်များအား total တွင် သွားပေါင်းထားမည် ဖြစ်ပါသည်။

ကျွှန်တော်တို့ ဒီနေရာတွင် စမ်းသပ်လိုသည်မှာ List အား ဖြစ်ပါသည်။ ထိုအတွက် စာကြောင်း List တစ်ခုအား new လုပ်ကာ အကြိမ် ၁သိန်း Loop လုပ်၍ null များအား ဖြည့်ထားစေပါသည်။ ပြီးပါက ထို list အား Thread ၅ခုဖြင့် အလုပ် လုပ်စေပါသည်။ Thread များသည် list အတွင်းမှ null များအား မကုန်မခြင်း remove လုပ်သွားမည် ဖြစ်သည်။ တစ်ခုခြင်း အလုပ်လုပ်သော အကြိမ်မှာ မတူညီနိုင်ပေမယ့် မှန်မှန်ကန်ကန် အလုပ်လုပ်သွားပါက နောက်ဆုံး အားလုံးပေါင်းရလဒ်သည် ၁သိန်း ဖြစ်ရမည်ဖြစ်သည်။ ကျွှန်တော်တို့ အထက်ပါ ပရိုဂရမ်အား စမ်းသပ်ကြည့်ပါမည်။


မှန်ကန်စွာ ဖော်ပြနိုင်ခြင်း မရှိကြောင်း တွေ့ရမည် ဖြစ်သည်။ အဘယ်ကြောင့်ဆိုသော် List သည် Thread Safeမဟုတ်သောကြောင့် ဖြစ်သည်။ List အား Thread Safe ဖြစ်အောင် ပြုပြင်ရေးသားကြည့်ပါမည်။

ThreadSafeSample2.java
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class ThreadSafeSample2 extends Thread{

    static int total = 0;
    private final List<?> list;
    
    public ThreadSafeSample2(List<?> list) {
        this.list = list;
    }
    
    @Override
    public void run() {
        int count = 0;
        while(list.remove(null))
            count++;
        
        System.out.println("Consume " + count + " Element");
        
        synchronized (this.getClass()) {
            total += count;
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        List<Thread> threads = new LinkedList<>();
        List<?> list = Collections.synchronizedList(new LinkedList<>());

        for (int i=0; i < 100000; i++)
            list.add(null);
        
        for (int i=0; i < 5; i++)
            threads.add(new ThreadSafeSample2(list));
        
        for (Thread t : threads)
            t.start();
            
        for (Thread o : threads)
            o.join();

        System.out.println("Total is " + total);
    }

}
အရင်ရေးထားသော နမှုရာအား စာကြောင်း ၂၉တွင် Collections#synchronizedList အား အသုံးပြု၍ List အား Thread Safe ဖြစ်အောင် ပြုပြင်ရေးထားပါသည်။ ၎င်းနမှုနာအား အလုပ်လုပ်ခိုင်း ကြည့်ပါမည်။

အထက်ပါအတိုင်း Total အား အကြိမ် ၁သိန်းဟု မှန်ကန်စွာ ဖော်ပြနိုင်သည်ကို တွေ့ရပါမည်။

ကိုးကား
http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html


ဆက်ပါဦးမည်။ လေးစားစွာဖြင့်။ 
မင်းလွင်

No comments:

Post a Comment