Concurrency, BlockingQueues (Java 7) - 1

"Hai, Amigo!"

"Hai, Kim!"

"Hari ini, saya akan memberitahu anda tentang concurrency."

" Concurrency ialah perpustakaan kelas Java yang merangkumi kelas khas yang telah dioptimumkan untuk kerja daripada pelbagai utas. Ini adalah topik yang sangat menarik dan meluas. Tetapi hari ini kita hanya akan mendapat pengenalan. Pakej itu dipanggil java.util. pakej serentak. Saya akan memberitahu anda tentang beberapa kelas yang menarik."

" Jenis atom. "

"Anda sudah tahu bahawa walaupun count++ bukanlah operasi selamat benang. Apabila pembolehubah ditambah dengan 1, tiga operasi sebenarnya berlaku. Akibatnya, mungkin terdapat konflik apabila pembolehubah diubah."

"Ya, Ellie memberitahu saya tidak lama dahulu:"

Benang 1 Benang 2 Hasilnya
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Tepat sekali. Kemudian Java menambah jenis data untuk melaksanakan operasi ini sebagai satu, iaitu secara atom (atom tidak boleh dibahagikan)."

"Sebagai contoh, Java mempunyai AtomicInteger, AtomicBoolean, AtomicDouble , dll."

"Andaikan kita perlu membuat kelas «kaunter»:"

Contoh
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

"Bagaimanakah anda akan menjadikan objek kelas ini selamat untuk benang?"

"Nah, saya akan membuat semua kaedah disegerakkan dan selesai dengannya:"

Contoh
class synchronized Counter
{
 private int c = 0;

 public synchronized void increment()
 {
  c++;
 }

 public synchronized void decrement()
 {
  c--;
 }

 public synchronized int value()
 {
  return c;
 }
}

"Kerja bagus. Tetapi, bagaimana rupanya jika kita menggunakan jenis atom:"

Contoh
class AtomicCounter
{
 private AtomicInteger c = new AtomicInteger(0);

 public void increment()
 {
  c.incrementAndGet();
 }

 public void decrement()
 {
  c.decrementAndGet();
 }

 public int value()
 {
  return c.get();
 }
}

"Kelas anda dan kelas saya berfungsi dengan cara yang sama, tetapi kelas dengan AtomicInteger berfungsi lebih cepat."

"Nah, adakah perbezaan kecil?"

"Ya. Berdasarkan pengalaman saya, saya sentiasa mengesyorkan mendahului dengan disegerakkan. Hanya apabila semua kod aplikasi telah ditulis dan proses pengoptimuman telah bermula barulah anda mula menulis semula kod untuk menggunakan jenis atom. Tetapi dalam apa jua keadaan, saya mahukan anda untuk mengetahui bahawa jenis sedemikian wujud. Walaupun anda tidak menggunakannya secara aktif, sentiasa ada peluang anda akan menemui kod di mana ia digunakan."

"Saya setuju. Itu masuk akal."

"Dengan cara ini, adakah anda perasan bahawa jenis atom tidak boleh diubah ? Berbeza dengan kelas Integer standard , AtomicInteger mengandungi kaedah untuk menukar keadaan dalamannya."

"Faham. Sama seperti String dan StringBuffer ."

"Ya, sesuatu seperti itu."

" Koleksi selamat benang. "

"Sebagai contoh koleksi sedemikian, bolehkah saya membentangkan ConcurrentHashMap. Bagaimanakah anda boleh menjadikan HashMap thread-safe?"

"Jadikan semua kaedahnya disegerakkan?"

"Sudah tentu, tetapi sekarang bayangkan bahawa anda mempunyai satu SynchronizedHashMap sedemikian, dan berpuluh-puluh utas mengaksesnya. Dan seratus kali sesaat, entri baharu ditambahkan pada peta, dan dalam proses keseluruhan objek dikunci untuk membaca dan menulis."

"Nah, ini pendekatan standard. Apa yang boleh anda lakukan?"

"Pencipta Java menghasilkan beberapa perkara yang menarik."

"Pertama, mereka menyimpan data dalam ConcurrentHashMap dalam satu blok, tetapi membahagikannya kepada bahagian yang dipanggil 'baldi'. Dan apabila seseorang menukar data dalam ConcurrentHashMap, maka kami hanya mengunci baldi yang sedang diakses, bukannya keseluruhan objek. Dalam lain perkataan, banyak benang boleh menukar objek secara serentak."

"Kedua, adakah anda ingat bahawa anda tidak boleh mengulangi elemen senarai/peta dan menukar senarai pada masa yang sama? Kod tersebut akan memberikan pengecualian:"

Jangan ulangi elemen koleksi dalam gelung dan ubahnya secara serentak
HashMap<String, Integer> map = new HashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"Tetapi dalam ConcurrentHashMap, anda boleh:"

Jangan ulangi elemen koleksi dalam gelung dan ubahnya serentak"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"Pakej serentak mempunyai banyak kelebihan. Kita hanya perlu memahami kelas ini dengan baik untuk menggunakannya."

"Saya faham. Terima kasih, Kim. Ini adalah kelas yang benar-benar menarik. Saya harap suatu hari nanti saya akan menguasainya seperti seorang virtuoso."