Thread lagi : Penggunaan wait() dan synchronized().

Pada awalnya kita sering bingung mengenai penggunaan synchronized() dan wait().

Misalnya pada contoh berikut :

class SuatuThread {

Object obj;

public SuatuThread(Object obj){

this.obj = obj;

}

public void run(){

synchronized (obj) {

obj.wait();

}

}

}

Disini kita sering rancu mengenai baris : obj.wait();

Pengertian awal kita adalah method wait() ini mestinya dipanggil oleh thread untuk menunggu giliran memakai Object obj, tetapi yang kita lihat adalah wait() dipanggil oleh obj itu sendiri (resource yg sedang di-sharing/di-lock/di-synchronized).

Untuk membenahi hal ini kita perlu mengingat bahwa method wait() bukan method dari kelas Thread, melainkan method bawaan dari kelas Object.

Jadi pengertian dari obj.wait()bukan berarti si obj yang menunggu (wait), melainkan berarti thread yang bersangkutan akan menunggu (wait) sampai thread lain selesai menggunakan obj (bisa dilihat di javadoc bagian penjelasan method wait()).

Locking/synchronizing lebih dekat hubungannya dengan suatu object bukan dengan thread, karena thread hanya memerlukan synchronization ketika dia bekerja dengan shared-object.

Maka dari itu di Java, wait() and notify() diasosiasikan dengan kelas Object.

Advertisements

Sinkronisasi, notify() dan notifyAll(), siapa membangunkan siapa?

“Bahwasanya sebuah resource bisa digunakan secara bersama-sama (sharing) tidak hanya oleh dua thread tetapi bisa banyak thread”. Ilustrasinya mungkin bisa dibayangkan pada WC umum (ahaha..):

Ketika thread A memakai resource WC, maka thread-thread yang lain harus menunggu (wait) thread A selesai memakai WC. Setelah A selesai, dia membuka pintu WC yang memberi tanda pada semua thread yang lain (notifyAll) bahwa WC sudah free of charge. Thread-thread yang lain pun berebut untuk mendapatkan hak berikutnya untuk memakai WC.

Dalam praktek Java, thread mana yg memperoleh hak tergantung dari JVM.

Notify() dan notifyAll() hampir sama, hanya saja pada notify() JVM hanya membangunkan salah satu thread secara random.

THREAD..

  • Thread adalah bagian di dalam program yang merupakan sebuah sekuens yang berdiri sendiri dan memiliki kontrol sendiri.
    • Setiap aplikasi java yang sedang berjalan sebenarnya memiliki minimal satu thread yaitu yang dipanggil dari method main().
    • Aplikasi yang memiliki lebih dari satu thread disebut aplikasi multi-threading.

    Extends Thread vs implements Runnable

    Kita tahu bahwa kita bisa membuat thread dengan dua cara tersebut di atas, tetapi pertanyaannya adalah kapan kita harus memakai cara yang satu dan bukan yang lain? Apa kelebihan metode yang satu dibandingkan yang lain?

    Alasan dan pendapat yang dikumpulkan:

    1. Phylosophical :

    • Dikatakan, meng-extends suatu kelas konkret selalu lebih berisiko dan bukan pilihan yang baik (Keuntungan abstraction).

    • According to Cay S. Horstmann and Gary Cornell in Core Java 2: Volume II – Advanced Features…

    “…forming a subclass of the Thread class … is no longer recommended. You should decouple the task that is to be run in parallel from the mechanism of running it.”

    1. Practical :

    • Lebih baik menggunakan interface Runnable karena dengan demikian kelas tersebut masih bisa meng-extends superclass lain.
    • Kelas Thread itu sendiri sebenarnya juga meng-implements Runnable, artinya jika kita extends Thread, sebenarnya kita secara tidak langsung juga implements Runnable, jadi kenapa kita tidak secara langsung meng-implements Runnable saja?

    hm.. barangkali ada alasan menarik lainnya..?

    Some issues @ JAVA COLLECTIONS FRAMEWORK

    While dwelling with the Java Collection Framework, some of us facing these interesting issues:

    1. Arrays.asList() behaviour

    This issue has been submitted as a bug in bugs.sun.com (bug_id=6353471) but the case is then closed and will not be fixed because it is considered “not a defect”.

    The bug report description said:

    java.util.Arrays.asList() does not support primitive arrays

    If the programmer passes an array of primative data type, for example:

    int[] intArray = { 1,2,3 };

    to the asList() method, it will accept that primative array and place it as the internal Object array’s first element.

    So a call to get(0) does not get you the first element that were in the primitive array (the value 1) but the array object itself

    Of course a call to get(1) with an index of 1 will result in an ArrayIndexOutOfBoundsException…

    And of course the toString() method (inherited from class Object) returns the hashcode of the array object, not the element of the array.

    This bug report is also found against 1.3 which is “Closed, and will not be fixed”… (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4348595)

    In that report, it is noted that if a primitive array was passed, the compiler would generate an error stating that it’s looking for an Object [] array and that a primitive cannot be passed… but with J2SE 5.0, it apparently can… not sure what the mechanisms that allows this.

    1. Exception issues from the method List.subList() and List.removeAll().

    It is similar with an article by Timothy Igor McGillicuty at

    http://radio.weblogs.com/0108008/categories/technology/

    Suppose we had an initialized array and,

    want to convert it to a List,

    creating a sublist from that list,

    then remove all elements from that list like what is exits on sublist

    At first we had this code:

    1 String[] str = {“Bob”, “Bill”, “Jean”};

    2 List list = Arrays.asList(arr);

    3 List sublist = list.subList(1,2);

    4 list.removeAll(sublist);

    Line 4 got us the java.util.ConcurrentModificationException

    The documentation says that a subList is dependent on the List that it is sublisting from. So, while a sublist is open, it is manipulating the parent list and seems to have a lock on it.

    Instead, you can create a brand new ArrayList and fill it with the subList, thus freeing up the sublist so that a future call can modify the original List.

    This is the modified line 3:

    3 List sublist = new ArrayList(list.subList(1,2));

    So why does

    3 List sublist = list.subList(1,2);

    get you a different animal than

    3 List sublist = new ArrayList(list.subList(1,2));?

    Answer : Because in the first snippet, we haven’t instantiated a new object, we just created a reference to an existing object.

    In the second snippet, we created a brand new object. That’s what the word “new” gets us.

    Right after we fixed that,

    Line 4 got us the java.util.UnsupportedOperationException

    The cause is similar with our previous problem. Note that the return from the method asList() doesn’t return a new object but it says that:

    Returns:

    a list view of the specified array

    So we have to instantiate a new object rather than just refering.

    This is the modified line 2:

    2 List list = new ArrayList(Arrays.asList(arr));