Konkurensi, BlockingQueues (Java 7) - 1

"Hai, Amigo!"

"Hai, Kim!"

"Hari ini, saya akan memberi tahu Anda tentang konkurensi."

" Concurrency adalah pustaka kelas Java yang menyertakan kelas khusus yang telah dioptimalkan untuk bekerja dari banyak utas. Ini adalah topik yang sangat menarik dan luas. Tapi hari ini kita hanya akan mendapatkan pengantar. Paket tersebut disebut java.util. paket bersamaan. Saya akan memberi tahu Anda tentang beberapa kelas yang menarik."

" Jenis atom. "

"Anda sudah tahu bahwa count++ bukanlah operasi thread-safe. Ketika sebuah variabel bertambah 1, tiga operasi benar-benar terjadi. Akibatnya, mungkin ada konflik ketika variabel diubah."

"Ya, Ellie memberitahuku belum lama ini:"

Utas 1 Utas 2 Hasil
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Tepat sekali. Kemudian Java menambahkan tipe data untuk melakukan operasi ini sebagai satu, yaitu secara atomik (atom tidak dapat dibagi)."

"Misalnya, Java memiliki AtomicInteger, AtomicBoolean, AtomicDouble , dll."

"Misalkan kita perlu membuat kelas «counter»:"

Contoh
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

"Bagaimana Anda membuat objek kelas ini aman untuk thread?"

"Baiklah, saya akan menyinkronkan semua metode dan menyelesaikannya:"

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. Tapi, seperti apa jadinya jika kita menggunakan tipe 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 bekerja dengan cara yang sama, tetapi kelas dengan AtomicInteger bekerja lebih cepat."

"Yah, apakah itu perbedaan kecil?"

"Ya. Berdasarkan pengalaman saya, saya selalu merekomendasikan memimpin dengan disinkronkan. Hanya ketika semua kode aplikasi telah ditulis dan proses pengoptimalan telah dimulai, Anda harus mulai menulis ulang kode untuk menggunakan tipe atom. Tetapi bagaimanapun juga, saya menginginkan Anda untuk mengetahui bahwa jenis seperti itu ada. Bahkan jika Anda tidak menggunakannya secara aktif, selalu ada kemungkinan Anda akan menemukan kode di mana mereka digunakan."

"Saya setuju. Itu masuk akal."

"Ngomong-ngomong, apakah Anda memperhatikan bahwa tipe atom tidak dapat diubah ? Berbeda dengan kelas Integer standar , AtomicInteger berisi metode untuk mengubah status internalnya."

"Mengerti. Sama seperti String dan StringBuffer ."

"Ya, sesuatu seperti itu."

" Koleksi aman benang. "

"Sebagai contoh koleksi semacam itu, bolehkah saya menyajikan ConcurrentHashMap. Bagaimana Anda membuat HashMap aman dari thread?"

"Buat semua metodenya disinkronkan?"

"Tentu, tapi sekarang bayangkan Anda memiliki satu SynchronizedHashMap, dan lusinan utas mengaksesnya. Dan seratus kali dalam satu detik entri baru ditambahkan ke peta, dan dalam prosesnya seluruh objek dikunci untuk membaca dan menulis."

"Yah, ini pendekatan standar. Apa yang bisa kamu lakukan?"

"Pencipta Java datang dengan beberapa hal keren."

"Pertama, mereka menyimpan data di ConcurrentHashMap dalam satu blok, tetapi membaginya menjadi beberapa bagian yang disebut 'ember'. Dan ketika seseorang mengubah data di ConcurrentHashMap, maka kami hanya mengunci ember yang sedang diakses, bukan seluruh objek. Di lainnya kata, banyak utas dapat mengubah objek secara bersamaan."

"Kedua, apakah Anda ingat bahwa Anda tidak dapat mengulangi elemen daftar/peta dan mengubah daftar pada saat yang sama? Kode seperti itu akan memunculkan pengecualian:"

Jangan mengulangi elemen koleksi dalam satu lingkaran dan mengubahnya secara bersamaan
HashMap<String, Integer> map = new HashMap<String, Integer>();

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

"Tapi di ConcurrentHashMap, Anda bisa:"

Jangan mengulangi elemen koleksi dalam satu lingkaran dan mengubahnya secara bersamaan"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

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

"Paket konkuren memiliki banyak keuntungan. Kita hanya perlu memahami kelas-kelas ini dengan sangat baik untuk menggunakannya."

"Begitu. Terima kasih, Kim. Ini benar-benar kelas yang menarik. Aku harap suatu hari nanti aku akan menguasainya seperti seorang virtuoso."