Samtidighet, blockeringsköer (Java 7) - 1

"Hej, Amigo!"

"Hej Kim!"

"Idag ska jag berätta om samtidighet."

" Concurrency är ett Java-klassbibliotek som innehåller specialklasser som har optimerats för arbete från flera trådar. Detta är ett mycket intressant och omfattande ämne. Men idag ska vi bara få en introduktion. Paketet heter java.util. samtidigt paket. Jag ska berätta om ett par intressanta klasser."

" Atomtyper. "

"Du vet redan att även count++ inte är en trådsäker operation. När en variabel ökas med 1 sker faktiskt tre operationer. Som ett resultat kan det uppstå en konflikt när variabeln ändras."

"Ja, Ellie sa till mig för inte så länge sedan:"

Tråd 1 Tråd 2 Resultat
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Exakt. Sedan lade Java till datatyper för att utföra dessa operationer som en, dvs atomärt (en atom är odelbar)."

"Till exempel har Java AtomicInteger, AtomicBoolean, AtomicDouble , etc."

"Anta att vi behöver göra en "räknare" klass:"

Exempel
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

"Hur skulle du göra föremål av denna klass trådsäkra?"

"Tja, jag skulle göra alla metoder synkroniserade och vara klar med det:"

Exempel
class synchronized Counter
{
 private int c = 0;

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

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

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

"Bra jobbat. Men hur skulle det se ut om vi använde atomtyper:"

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

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

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

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

"Din klass och min klass fungerar båda på samma sätt, men klassen med ett AtomicInteger fungerar snabbare."

"Nå, är det en liten skillnad?"

"Ja. Baserat på min erfarenhet rekommenderar jag alltid att leda med synkroniserat. Först när all applikationskod är skriven och optimeringsprocessen har börjat bör du börja skriva om koden för att använda atomtyperna. Men i alla fall ville jag ha dig att veta att sådana typer finns. Även om du inte aktivt använder dem, finns det alltid en chans att du stöter på kod där de används."

"Jag håller med. Det är vettigt."

"Förresten, märkte du att atomtyperna inte är oföränderliga ? I motsats till standardklassen Integer innehåller AtomicInteger metoder för att ändra dess interna tillstånd. "

"Förstår. Precis som String och StringBuffer ."

"Ja något liknande."

" Trådsäkra samlingar. "

"Får jag presentera ConcurrentHashMap som exempel på en sådan samling. Hur skulle du göra HashMap trådsäker?"

"Göra alla dess metoder synkroniserade?"

"Visst, men föreställ dig nu att du har en sådan SynchronizedHashMap och dussintals trådar som kommer åt den. Och hundra gånger i sekunden läggs en ny post till kartan, och i processen låses hela objektet för läsning och skrivning."

"Tja, det här är standardmetoden. Vad kan du göra?"

"Javas skapare kom på några coola saker."

"Först lagrar de data i en ConcurrentHashMap i ett enda block, men delar upp den i delar som kallas "buckets". Och när någon ändrar data i en ConcurrentHashMap, då låser vi bara den hink som nås, snarare än hela objektet. I andra ord, många trådar kan ändra objektet samtidigt."

"För det andra, kommer du ihåg att du inte kan iterera över elementen i listan/kartan och ändra listan samtidigt? Sådan kod kommer att skapa ett undantag:"

Iterera inte över elementen i en samling i en loop och ändra den samtidigt
HashMap<String, Integer> map = new HashMap<String, Integer>();

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

"Men i ConcurrentHashMap kan du:"

Iterera inte över elementen i en samling i en loop och ändra den samtidigt"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

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

"Det samtidiga paketet har många fördelar. Vi behöver bara förstå dessa klasser mycket väl för att kunna använda dem."

"Jag förstår. Tack, Kim. Det här är verkligen intressanta klasser. Jag hoppas att jag en dag kommer att bemästra dem som en virtuos."