Concurrency, BlockingQueues (Java 7) - 1

"Hi, Amigo!"

"Hi, Kim!"

"Ngayon, sasabihin ko sa iyo ang tungkol sa concurrency."

" Ang Concurrency ay isang library ng klase ng Java na may kasamang mga espesyal na klase na na-optimize para sa trabaho mula sa maraming mga thread. Ito ay isang napaka-interesante at malawak na paksa. Ngunit ngayon kami ay kukuha lamang ng isang panimula. Ang package ay tinatawag na java.util. concurrent package. Sasabihin ko sa iyo ang tungkol sa ilang mga kawili-wiling klase."

" Mga uri ng atom. "

"Alam mo na na kahit na ang count++ ay hindi isang thread-safe na operasyon. Kapag ang isang variable ay nadagdagan ng 1, tatlong operasyon ang aktwal na nagaganap. Bilang resulta, maaaring magkaroon ng salungatan kapag ang variable ay binago."

"Oo, sinabi sa akin ni Ellie kamakailan:"

Thread 1 Thread 2 Resulta
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Eksakto. Pagkatapos ay nagdagdag ang Java ng mga uri ng data upang maisagawa ang mga operasyong ito bilang isa, ibig sabihin, atomically (isang atom ay hindi mahahati)."

"Halimbawa, ang Java ay mayroong AtomicInteger, AtomicBoolean, AtomicDouble , atbp."

"Ipagpalagay na kailangan nating gumawa ng isang «counter» na klase:"

Halimbawa
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

"Paano mo gagawing ligtas ang thread ng klase na ito?"

"Buweno, gagawin kong naka-synchronize ang lahat ng mga pamamaraan at gagawin dito:"

Halimbawa
class synchronized Counter
{
 private int c = 0;

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

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

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

"Magandang trabaho. Ngunit, ano ang magiging hitsura kung gumamit kami ng mga uri ng atomic:"

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

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

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

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

"Ang iyong klase at ang aking klase ay parehong gumagana, ngunit ang klase na may AtomicInteger ay gumagana nang mas mabilis."

"Well, ito ba ay isang maliit na pagkakaiba?"

"Oo. Batay sa aking karanasan, palagi kong inirerekumenda ang pangunguna nang may naka-synchronize. Kapag naisulat na ang lahat ng application code at nagsimula na ang proseso ng pag-optimize, dapat mong simulan muli ang pagsulat ng code para magamit ang mga atomic na uri. Ngunit sa anumang kaso, gusto kita upang malaman na ang mga ganitong uri ay umiiral. Kahit na hindi mo aktibong ginagamit ang mga ito, palaging may pagkakataong makatagpo ka ng code kung saan ginagamit ang mga ito."

"I agree. That makes sense."

"Nga pala, napansin mo ba na ang mga atomic na uri ay hindi nababago ? Sa kaibahan sa karaniwang klase ng Integer , ang AtomicInteger ay naglalaman ng mga pamamaraan para sa pagbabago ng panloob na estado nito."

"Got it. Parang String at StringBuffer ."

"Oo, may ganyan."

" Mga koleksyon na ligtas sa thread. "

"Bilang halimbawa ng naturang koleksyon, maaari kong ipakita ang ConcurrentHashMap. Paano mo gagawing ligtas ang thread ng HashMap?"

"Gawing naka-synchronize ang lahat ng pamamaraan nito?"

"Oo naman, ngunit ngayon isipin na mayroon kang isang tulad na SynchronizedHashMap, at dose-dosenang mga thread na nag-a-access dito. At isang daang beses sa isang segundo isang bagong entry ang idinagdag sa mapa, at sa proseso ang buong bagay ay naka-lock para sa pagbabasa at pagsusulat."

"Well, ito ang standard approach. Ano ang magagawa mo?"

"Nagbigay ang mga tagalikha ng Java ng ilang mga cool na bagay."

"Una, nag-iimbak sila ng data sa isang ConcurrentHashMap sa isang bloke, ngunit hinahati ito sa mga bahaging tinatawag na 'mga bucket'. At kapag may nagpalit ng data sa isang ConcurrentHashMap, ni-lock lang namin ang bucket na ina-access, sa halip na ang buong bagay. Sa iba pa salita, maraming mga thread ang maaaring baguhin ang bagay nang sabay-sabay."

"Pangalawa, natatandaan mo ba na hindi ka maaaring umulit sa mga elemento ng listahan/mapa at baguhin ang listahan nang sabay-sabay? Magbibigay ng exception ang naturang code:"

Huwag umulit sa mga elemento ng isang koleksyon sa isang loop at sabay-sabay na baguhin ito
HashMap<String, Integer> map = new HashMap<String, Integer>();

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

"Ngunit sa ConcurrentHashMap, maaari mong:"

Huwag umulit sa mga elemento ng isang koleksyon sa isang loop at sabay-sabay na baguhin ito"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

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

"Ang kasabay na pakete ay may maraming mga pakinabang. Kailangan lang nating maunawaan nang mabuti ang mga klase na ito upang magamit ang mga ito."

"I see. Thanks, Kim. These are truly interesting classes. Sana balang araw ay ma-master ko sila na parang birtuoso."