View
216
Download
0
Category
Preview:
Citation preview
7/27/2019 java.util.concurrent.docx
1/13
Cinco coisas que voc no sabia sobre...
java.util.concurrent, Parte 1
Programao multiencadeada com colees simultneas
Ted Neward, Principal, Neward & Associates
Resumo: A composio de cdigos multiencadeados que executam corretamente e
protegem aplicativos contra danos muito difcil por isso que existe o
java.util.concurrent . Ted Neward mostra como as classes de colees simultneas
como CopyOnWriteArrayList , BlockingQueuee ConcurrentMap aperfeioam as
classes de colees padro para suas necessidades de programao simultnea.
Data: 17/Mai/2011
Nvel: IntrodutrioTambm disponvel em :Ingls
Atividade: 2127 visualizaes
Comentrios: 0 (Visualizar|Incluir comentrio- Conectar)
Mdia de classificao (2 votos)
Classificar este artigo
Sobre esta srie
Ento, voc acha que possui conhecimento sobre programao Java? A verdade que a
maioria dos desenvolvedores tem apenas algum conhecimento sobre a plataforma Java,
aprendendo o suficiente para concluir a tarefa. Nestasrie, Ted Neward examina a
fundo a funcionalidade da plataforma Java para revelar fatos pouco conhecidos que
podem lhe ajudar a superar at mesmo os desafios de programao mais difceis.
As colees simultneas foram uma grande incluso no Java 5, mas muitos
desenvolvedores Java ignoraram essa incluso devido grande propaganda sobre
anotaes e genricos. Alm disso, e para falar a verdade, muitos desenvolvedores
evitam esse pacote porque acreditam que ele, assim como os problemas que ele pretende
resolver, complicado.
Na verdade, o java.util.concurrent contm muitas classes que resolvem de forma
efetiva problemas de simultaneidade comuns, sem a necessidade de um trabalho rduo.
Leia sobre como as classes java.util.concurrent como CopyOnWriteArrayList e
BlockingQueue ajudam a resolver os desafios prejudiciais de programao
multiencadeada.
1. TimeUnit
Apesar de no ser uma classe de coleespor assim dizer, a enumeraojava.util.concurrent.TimeUnit facilita muito a leitura do cdigo. O uso do
http://www.ibm.com/developerworks/br/java/library/j-5things4/#author1http://www.ibm.com/developerworks/br/java/library/j-5things4/#author1http://www.ibm.com/developerworks/library/j-5things4/index.htmlhttp://www.ibm.com/developerworks/library/j-5things4/index.htmlhttp://www.ibm.com/developerworks/library/j-5things4/index.htmlhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#icommentshttp://www.ibm.com/developerworks/br/java/library/j-5things4/#icommentshttp://www.ibm.com/developerworks/br/java/library/j-5things4/#icommentshttp://www.ibm.com/developerworks/br/java/library/j-5things4/http://www.ibm.com/developerworks/br/java/library/j-5things4/http://www.ibm.com/developerworks/br/java/library/j-5things4/http://www.ibm.com/developerworks/br/java/library/j-5things4/#iratingshttp://www.ibm.com/developerworks/br/java/library/j-5things4/#iratingshttp://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=5+things+you+didhttp://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=5+things+you+didhttp://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=5+things+you+didhttp://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=5+things+you+didhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#iratingshttp://www.ibm.com/developerworks/br/java/library/j-5things4/http://www.ibm.com/developerworks/br/java/library/j-5things4/#icommentshttp://www.ibm.com/developerworks/library/j-5things4/index.htmlhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#author17/27/2019 java.util.concurrent.docx
2/13
TimeUnit livra os desenvolvedores que usam mtodo ou API do controle do
milissegundo.
O TimeUnit incorpora todas as unidades de tempo, desde de MILISSEGUNDOS e
MICROSSEGUNDOS at DIAS e HORAS, o que significa que ele manipula praticamente todos
os tipos de intervalos de tempo necessrios para o desenvolvedor. E, graas aos mtodosde converso declarados na enumerao, ainda mais simples converterHORAS em
MILISSEGUNDOS quando o tempo acelera.
Voltar para parte superior
2. CopyOnWriteArrayList
A execuo de uma nova cpia de um array uma operao muito cara, em termos de
tempo e sobrecarga de memria, para ser usada normalmente, muitas vezes os
desenvolvedores preferem usar um ArrayList sincronizado. No entanto, essa tambm
uma opo cara, pois todas as vezes que repetida nos contedos de uma coleo
necessrio sincronizar todas as operaes, incluindo leitura e gravao, para garantir a
consistncia.
Isso retrocede a estrutura de custo em cenrios nos quais diversos leitores leem o
ArrayList , mas poucos o modificam.
CopyOnWriteArrayList o que resolve esse problema. Seu Javadoc define
CopyOnWriteArrayList como uma "variante thread-safe do ArrayList na qual todasas operaes variveis (add, set entre outras) so implementadas atravs da criao de
uma nova cpia do array".
A coleo copia internamente o seu contedo para um novo array em caso de
modificao, dessa forma os leitores que acessam os contedos do array no ficam
sujeitos aos custos de sincronizao (pois no esto operando em dados variveis).
Basicamente, o CopyOnWriteArrayList ideal para o cenrio no qual o ArrayList
falha: leitura frequente e gravao rara, como os ouvintesde um evento JavaBean.
Voltar para parte superior
3. BlockingQueue
A interface BlockingQueue declara ser uma Fila, o que significa que seus itens so
armazenados na ordem first in, first out (FIFO). Os itens inseridos em uma ordemespecfica so recuperados na mesma ordemmas com a incluso da garantia de que
qualquer tentativa de recuperao de um item de uma fila vazia ir bloquear o
encadeamento de chamada at que o item esteja pronto para ser recuperado. Da mesma
forma, qualquer tentativa de insero de um item em uma fila cheia ir bloquear o
encadeamento de chamada at que haja espao disponvel no armazenamento da fila.
http://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pcon7/27/2019 java.util.concurrent.docx
3/13
O BlockingQueue resolve perfeitamente o problema de como "transferir" itens reunidos
por um encadeamento para outro encadeamento para processamento, sem a preocupao
com problemas de sincronizao. A trilha de blocos protegidos no tutorial do Java um
bom exemplo. Ela desenvolve um buffer delimitado com um nico intervalo usando
sincronizao manual e wait()/notifyAll() para sinalizar entre os encadeamentos
quando um novo item est disponvel para consumo e quando o intervalo est prontopara ser preenchido com um novo item. (Consulte a seo deimplementao de blocos
protegidospara obter mais detalhes.)
Apesar do cdigo no tutorial de blocos protegidos funcionar, ele longo, complicado e
no totalmente intuitivo. No comeo da plataforma Java, os desenvolvedores
realmente tinham que lidar com tais cdigos, mas em 2010as coisas certamente
melhoraram, no?
A Listagem 1 mostra uma verso reescrita do cdigo dos blocos protegidos na qual foi
empregado o ArrayBlockingQueue ao invs da verso manual Drop.
Listagem 1. BlockingQueueimport java.util.*;
import java.util.concurrent.*;
class Producer
implements Runnable
{
private BlockingQueue drop;
List messages = Arrays.asList(
"Mares eat oats",
"Does eat oats","Little lambs eat ivy",
"Wouldn't you eat ivy too?");
public Producer(BlockingQueue d) { this.drop = d; }
public void run()
{
try
{
for (String s : messages)
drop.put(s);
drop.put("DONE");
}
catch (InterruptedException intEx)
{
System.out.println("Interrupted! " +
"Last one out, turn out the lights!");
}
}
}
class Consumer
implements Runnable
{
private BlockingQueue drop;
public Consumer(BlockingQueue d) { this.drop = d; }
public void run()
http://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.htmlhttp://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.htmlhttp://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.htmlhttp://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.htmlhttp://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.htmlhttp://java.sun.com/docs/books/tutorial/essential/concurrency/guardmeth.html7/27/2019 java.util.concurrent.docx
4/13
{
try
{
String msg = null;
while (!((msg = drop.take()).equals("DONE")))
System.out.println(msg);
}catch (InterruptedException intEx)
{
System.out.println("Interrupted! " +
"Last one out, turn out the lights!");
}
}
}
public class ABQApp
{
public static void main(String[] args)
{
BlockingQueue drop = new ArrayBlockingQueue(1, true);
(new Thread(new Producer(drop))).start();
(new Thread(new Consumer(drop))).start();
}
}
O ArrayBlockingQueue tambm cumpre a "integridade"o que significa que ele
pode conceder aos encadeamentos de leitura e gravao o acesso primeiro a entrar,
primeiro a sair. A alternativa seria uma poltica mais eficiente que poderia deixar alguns
encadeamentos sem processamento. (Ou seja, seria mais eficiente permitir a execuo
de leitores enquanto outros leitores permanecem bloqueados, mas isso poderia gerar um
fluxo constante de encadeamentos de leitores o que impediria os gravadores deexecutarem sua tarefa.)
Vigilncia de erro!
A propsito, voc estava certo se observou que os blocos protegidos contm um grande
erroo que aconteceria se um desenvolvedor sincronizasse a instncia Drop dentro de
main()?
O BlockingQueue tambm oferece suporte para mtodos que usam parmetros de
tempo, indicando quanto tempo o segmento deve permanecer bloqueado antes deretornar a falha de sinal para inserir ou recuperar o item em questo. Isso evita uma
espera ilimitada, o que poderia ser fatal para um sistema de produo, visto que uma
espera ilimitada pode se tornar facilmente uma queda do sistema que requer a
reinicializao.
Voltar para parte superior
4. ConcurrentMap
http://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pcon7/27/2019 java.util.concurrent.docx
5/13
O map possui um erro de simultaneidade sutil que j prejudicou muitos desenvolvedores
Java desatentos. ConcurrentMap a soluo simples.
Quando um Map acessado de diversos encadeamentos, comum usarcontainsKey()
ou get() para descobrir se uma determinada chave est presente antes de armazenar o
par chave/valor. Mas mesmo com um Mapsincronizado, um encadeamento poderiapenetrar durante esse processo e confiscar o controle do Map. O problema que o
bloqueio obtido no comeo de get()e liberado antes do bloqueio poder ser adquirido
novamente, no chamado para put(). O resultado uma disputa entre dois
encadeamentos e o resultado ser diferente dependendo do encadeamento que for
executado primeiro.
Se dois encadeamentos chamarem um mtodo ao mesmo tempo, ambos iro testar e
efetuar a incluso, desperdiando o valor do primeiro encadeamento no processo.
Felizmente, a interface ConcurrentMap oferece suporte para diversos mtodos
adicionais projetados para executar duas tarefas com um nico bloqueio:
putIfAbsent(), por exemplo, executa o teste primeiro e, em seguida, executa a
incluso somente se a chave no estiver armazenada em Map.
Voltar para parte superior
5. SynchronousQueues
SynchronousQueue um item interessante, de acordo com o Javadoc:
Uma fila de bloqueio na qual cada operao de insero deve aguardar uma operao de
remoo correspondente por outro encadeamento, e vice-versa. Uma fila sncrona no
possui nenhuma capacidade interna, nem mesmo a capacidade para um item.
O SynchronousQueue basicamente outra implementao do supramencionado
BlockingQueue. Ele fornece uma maneira leve de trocar elementos nicos de um
encadeamento para outro, usando a semntica de bloqueio usada por
ArrayBlockingQueue . Na Listagem 2, eu reescrevi o cdigo daListagem 1usando
SynchronousQueue ao invs de ArrayBlockingQueue:
Listagem 2. SynchronousQueueimport java.util.*;
import java.util.concurrent.*;
class Producer
implements Runnable
{
private BlockingQueue drop;
List messages = Arrays.asList(
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"Wouldn't you eat ivy too?");
http://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#listing1http://www.ibm.com/developerworks/br/java/library/j-5things4/#listing1http://www.ibm.com/developerworks/br/java/library/j-5things4/#listing1http://www.ibm.com/developerworks/br/java/library/j-5things4/#listing1http://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pcon7/27/2019 java.util.concurrent.docx
6/13
public Producer(BlockingQueue d) { this.drop = d; }
public void run()
{
try
{
for (String s : messages)drop.put(s);
drop.put("DONE");
}
catch (InterruptedException intEx)
{
System.out.println("Interrupted! " +
"Last one out, turn out the lights!");
}
}
}
class Consumer
implements Runnable
{
private BlockingQueue drop;
public Consumer(BlockingQueue d) { this.drop = d; }
public void run()
{
try
{
String msg = null;
while (!((msg = drop.take()).equals("DONE")))
System.out.println(msg);
}
catch (InterruptedException intEx)
{
System.out.println("Interrupted! " +
"Last one out, turn out the lights!");
}
}
}
public class SynQApp
{
public static void main(String[] args)
{
BlockingQueue drop = new SynchronousQueue();
(new Thread(new Producer(drop))).start();
(new Thread(new Consumer(drop))).start();}
}
O cdigo de implementao parece quase igual, mas o aplicativo inclui um benefcio, o
SynchronousQueue permitir uma insero na fila somente se houver umencadeamento aguardando para utiliz-lo.
Na prtica, o SynchronousQueue similar aos "canais rendezvous" disponveis em
linguagens como Ada ou CSP. Em outros ambientes, eles tambm so conhecidos como
"junes" incluindo o .NET (consulte a seoRecursos).
http://www.ibm.com/developerworks/br/java/library/j-5things4/#resourceshttp://www.ibm.com/developerworks/br/java/library/j-5things4/#resourceshttp://www.ibm.com/developerworks/br/java/library/j-5things4/#resourceshttp://www.ibm.com/developerworks/br/java/library/j-5things4/#resources7/27/2019 java.util.concurrent.docx
7/13
Voltar para parte superior
Concluso
Por que brigar com a introduo de simultaneidade em suas classes de coleo quando a
biblioteca do Java Runtime oferece equivalentes teis pr-desenvolvidos?O prximo
artigodesta sria explora ainda mais o namespace java.util.concurrent .
5 things you didn't know about ...
java.util.concurrent, Part 2
Concurrent programming means working smarter, not harder
Ted Neward, Principal, Neward & Associates
Summary: In addition to concurrency-friendly Collections, java.util.concurrent
introduced other pre-built components that can assist you in regulating and executing
threads in multithreaded applications. Ted Neward introduces five more of his Java
programming must-haves from the java.util.concurrent package.
Date: 01 Jun 2010
Level: Introductory
PDF:A4 and Letter(195 KB | 9 pages)Get Adobe Reader
Also available in:ChineseKoreanRussianJapaneseVietnamesePortuguese
Activity: 17739 views
Comments: 12 (View|Add comment- Sign in)
Average rating (35 votes)
Rate this article
Concurrent Collections make concurrent programming easier by providing thread-safe,
well-tuned data structures. In some cases, however, developers need to go one step
further, and think about regulating and/or throttling thread execution. Given that thewhole point ofjava.util.concurrent is to simplify multithreaded programming, you
might hope the package would include synchronization utilitiesand it does.
This article, a follow-up toPart 1, introduces several synchronization constructs that are
a higher level than the core language primitives (monitors), but not so high that they're
buried inside a Collection class. Using these locks and gates is fairly straightforward
once you know what they're for.
About this series
http://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pconhttps://www.ibm.com/developerworks/java/library/j-5things5.htmlhttps://www.ibm.com/developerworks/java/library/j-5things5.htmlhttps://www.ibm.com/developerworks/java/library/j-5things5.htmlhttps://www.ibm.com/developerworks/java/library/j-5things5.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#author1http://www.ibm.com/developerworks/java/library/j-5things5/index.html#author1http://www.ibm.com/developerworks/java/library/j-5things5/j-5things5-pdf.pdfhttp://www.ibm.com/developerworks/java/library/j-5things5/j-5things5-pdf.pdfhttp://www.ibm.com/developerworks/java/library/j-5things5/j-5things5-pdf.pdfhttp://www.adobe.com/products/acrobat/readstep2.htmlhttp://www.adobe.com/products/acrobat/readstep2.htmlhttp://www.adobe.com/products/acrobat/readstep2.htmlhttp://www.ibm.com/developerworks/cn/java/j-5things5.htmlhttp://www.ibm.com/developerworks/cn/java/j-5things5.htmlhttp://www.ibm.com/developerworks/kr/library/j-5things5.htmlhttp://www.ibm.com/developerworks/kr/library/j-5things5.htmlhttp://www.ibm.com/developerworks/ru/library/j-5things5/http://www.ibm.com/developerworks/ru/library/j-5things5/http://www.ibm.com/developerworks/jp/java/library/j-5things5.htmlhttp://www.ibm.com/developerworks/jp/java/library/j-5things5.htmlhttp://www.ibm.com/developerworks/vn/library/12/j-5things5/http://www.ibm.com/developerworks/vn/library/12/j-5things5/http://www.ibm.com/developerworks/br/java/library/j-5things5/http://www.ibm.com/developerworks/br/java/library/j-5things5/http://www.ibm.com/developerworks/br/java/library/j-5things5/http://www.ibm.com/developerworks/java/library/j-5things5/index.html#icommentshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#icommentshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#icommentshttp://www.ibm.com/developerworks/java/library/j-5things5/index.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#iratingshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#iratingshttps://www.ibm.com/developerworks/java/library/j-5things4.htmlhttps://www.ibm.com/developerworks/java/library/j-5things4.htmlhttps://www.ibm.com/developerworks/java/library/j-5things4.htmlhttps://www.ibm.com/developerworks/java/library/j-5things4.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#iratingshttp://www.ibm.com/developerworks/java/library/j-5things5/index.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#icommentshttp://www.ibm.com/developerworks/br/java/library/j-5things5/http://www.ibm.com/developerworks/vn/library/12/j-5things5/http://www.ibm.com/developerworks/jp/java/library/j-5things5.htmlhttp://www.ibm.com/developerworks/ru/library/j-5things5/http://www.ibm.com/developerworks/kr/library/j-5things5.htmlhttp://www.ibm.com/developerworks/cn/java/j-5things5.htmlhttp://www.adobe.com/products/acrobat/readstep2.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/j-5things5-pdf.pdfhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#author1https://www.ibm.com/developerworks/java/library/j-5things5.htmlhttps://www.ibm.com/developerworks/java/library/j-5things5.htmlhttp://www.ibm.com/developerworks/br/java/library/j-5things4/#ibm-pcon7/27/2019 java.util.concurrent.docx
8/13
So you think you know about Java programming? The fact is, most developers scratch
the surface of the Java platform, learning just enough to get the job done. In thisseries,
Ted Neward digs beneath the core functionality of the Java platform to uncover little-
known facts that could help you solve even the stickiest programming challenges.
1. Semaphore
In some enterprise systems, it's not uncommon for developers to need to throttle the
number of open requests (threads/actions) against a particular resourcein fact,
throttling can sometimes improve the throughput of a system by reducing the amount of
contention against that particular resource. While it's certainly possible to try to write
the throttling code by hand, it's easier to use the semaphore class, which takes care of
throttling for you, as shown in Listing 1:
Listing 1. Use Semaphore to throttle
import java.util.*;import java.util.concurrent.*;
public class SemApp
{
public static void main(String[] args)
{
Runnable limitedCall = new Runnable() {
final Random rand = new Random();
final Semaphore available = new Semaphore(3);
int count = 0;
public void run()
{
int time = rand.nextInt(15);
int num = count++;
try
{
available.acquire();
System.out.println("Executing " +
"long-running action for " +
time + " seconds... #" + num);
Thread.sleep(time * 1000);
System.out.println("Done with #" +
num + "!");
available.release();
}
catch (InterruptedException intEx)
{
intEx.printStackTrace();
}
}
};
for (int i=0; i
7/27/2019 java.util.concurrent.docx
9/13
Even though the 10 threads in this sample are running (which you can verify by
executing jstack against the Java process running SemApp), only three are active. The
other seven are held at bay until one of the semaphore counts is released. (Actually, the
Semaphore class supports acquiring and releasing more than onepermitat a time, butthat wouldn't make sense in this scenario.)
Back to top
2. CountDownLatch
Develop skills on this topic
This content is part of progressive knowledge paths for advancing your skills. See:
Become a Java developer Java concurrency
IfSemaphore is the concurrency class designed to allow threads "in" one at a time
(perhaps evoking memories of bouncers at popular nightclubs), then CountDownLatch
is the starting gate at a horse race. This class holds all threads at bay until a particular
condition is met, at which point it releases them all at once.
Listing 2. CountDownLatch: Let's go to the races!
import java.util.*;import java.util.concurrent.*;
class Race
{
private Random rand = new Random();
private int distance = rand.nextInt(250);
private CountDownLatch start;
private CountDownLatch finish;
private List horses = new ArrayList();
public Race(String... names){
this.horses.addAll(Arrays.asList(names));
}
public void run()
throws InterruptedException
{
System.out.println("And the horses are stepping up to the
gate...");
final CountDownLatch start = new CountDownLatch(1);
final CountDownLatch finish = new
CountDownLatch(horses.size());
final List places =Collections.synchronizedList(new ArrayList());
http://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/training/kp/j-kp-intro/index.htmlhttp://www.ibm.com/developerworks/training/kp/j-kp-intro/index.htmlhttp://www.ibm.com/developerworks/training/kp/j-kp-concurrency/index.htmlhttp://www.ibm.com/developerworks/training/kp/j-kp-concurrency/index.htmlhttp://www.ibm.com/developerworks/training/kp/j-kp-concurrency/index.htmlhttp://www.ibm.com/developerworks/training/kp/j-kp-intro/index.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pcon7/27/2019 java.util.concurrent.docx
10/13
for (final String h : horses)
{
new Thread(new Runnable() {
public void run() {
try
{
System.out.println(h +" stepping up to the gate...");
start.await();
int traveled = 0;
while (traveled < distance)
{
// In a 0-2 second period of time....
Thread.sleep(rand.nextInt(3) * 1000);
// ... a horse travels 0-14 lengths
traveled += rand.nextInt(15);
System.out.println(h +
" advanced to " + traveled + "!");
}
finish.countDown();
System.out.println(h +
" crossed the finish!");
places.add(h);
}
catch (InterruptedException intEx)
{
System.out.println("ABORTING RACE!!!");
intEx.printStackTrace();
}
}
}).start();
}
System.out.println("And... they're off!");
start.countDown();
finish.await();
System.out.println("And we have our winners!");
System.out.println(places.get(0) + " took the gold...");
System.out.println(places.get(1) + " got the silver...");
System.out.println("and " + places.get(2) + " took home the
bronze.");
}
}
public class CDLApp
{
public static void main(String[] args)
throws InterruptedException, java.io.IOException
{
System.out.println("Prepping...");
Race r = new Race(
"Beverly Takes a Bath",
"RockerHorse",
"Phineas",
"Ferb",
"Tin Cup","I'm Faster Than a Monkey",
7/27/2019 java.util.concurrent.docx
11/13
"Glue Factory Reject"
);
System.out.println("It's a race of " + r.getDistance() + "
lengths");
System.out.println("Press Enter to run the race....");System.in.read();
r.run();
}
}
Notice inListing 2that CountDownLatch serves two purposes: First it releases all of the
threads simultaneously, simulating the start of the race; but later a different latch
simulates the end of the race, essentially so that the "main" thread can print out the
results. For a race with more commentary, you could add CountDownLatches at the
"turns" and "halfway" points of the race, as horses crossed the quarter, half, and three-quarter values in the distance.
Back to top
3. Executor
The examples inListing 1andListing 2both suffer from a fairly frustrating flaw, in that
they force you to create Thread objects directly. This is a recipe for trouble because in
some JVMs, creating a Thread is a heavyweight operation, and it's far better to reuse
existing Threads than to create new ones. In other JVMs, however, it's exactly the
opposite: Threads are pretty lightweight, and it's far better to just new-up one when you
need it. Of course, if Murphy has his way (which he usually does), whichever approach
you use will be exactly the wrong one for the platform you end up deploying on.
The JSR-166 expert group (seeResources) anticipated this situation, to some degree.
Rather than have Java developers create Threads directly, they introduced the
Executor interface, an abstraction for making new threads. As shown in Listing 3,
Executor allows you to create threads without having to new the Thread objects
yourself:
Listing 3. ExecutorExecutor exec = getAnExecutorFromSomeplace();
exec.execute(new Runnable() { ... });
The main drawback to using Executor is the same one we encounter with all factories:the factory has to come from someplace. Unfortunately, unlike the CLR, the JVM
doesn't ship with a standard VM-wide thread pool.
http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing2http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing2http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing2http://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing1http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing1http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing1http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing2http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing2http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing2http://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing2http://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing1http://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#listing27/27/2019 java.util.concurrent.docx
12/13
The Executor class does serve as a common place to get Executor-implementing
instances, but it only has new methods (to create a new thread pool, for example); it
doesn't have precreated instances. So you are on your own if you want to create and use
Executor instances throughout your code. (Or, in some cases, you will be able to use an
instance provided by your container/platform of choice.)
ExecutorService, at your service
As useful as it is to not have to worry about where Threads come from, the Executor
interface lacks some functionality that a Java developer might expect, such as the ability
to kick off a thread designed to produce a result and wait in a non-blocking fashion until
that result becomes available. (This is a common need in desktop applications, where a
user will execute a UI operation that requires accessing a database, and yet could want
to cancel the operation before it completes if it takes too long.)
For this, the JSR-166 experts created a far more useful abstraction, the
ExecutorService interface, which models the thread-starting factory as a service that
can be controlled collectively. For example, rather than calling execute() once for
each task, the ExecutorService could take a collection of tasks and return aList of
Futures representing the future results of each of those tasks.
Back to top
4. ScheduledExecutorServices
As great as the ExecutorService interface is, certain tasks need to be done in a
scheduled fashion, such as executing a given task at determined intervals or at a specific
time. This is the province of the ScheduledExecutorService, which extends
ExecutorService.
If your goal was to create a "heartbeat" command that "pinged" every five seconds,
ScheduledExecutorService would make it as simple as what you see in Listing 4:
Listing 4. ScheduledExecutorService 'pings' on schedule
import java.util.concurrent.*;
public class Ping
{
public static void main(String[] args)
{
ScheduledExecutorService ses =
Executors.newScheduledThreadPool(1);
Runnable pinger = new Runnable() {
public void run() {
System.out.println("PING!");
}
};
ses.scheduleAtFixedRate(pinger, 5, 5, TimeUnit.SECONDS);}
}
http://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pcon7/27/2019 java.util.concurrent.docx
13/13
How about that? No fussing with threads, no fussing with what to do if the user wants to
cancel the heartbeat, no explicitly marking threads as foreground or background; just
leave all those scheduling details to ScheduledExecutorService .
Incidentally, if a user did want to cancel the heartbeat, the return from the
scheduleAtFixedRate call would be a ScheduledFuture instance, which not only
wraps around the result if there is one, but also has a cancel method to shut down the
scheduled operation.
Back to top
5. Timeout methods
The ability to put a concrete timeout around blocking operations (and thus avoid
deadlocks) is one of the great advances of the java.util.concurrent library over its
older concurrency cousins, such as monitors for locking.
These methods are almost always overloaded with an int/TimeUnit pair, indicatinghow long the method should wait before bailing out and returning control to the
program. It requires more work on the part of the developerhow will you recover if
the lock isn't acquired?but the results are almost always more correct: fewer
deadlocks and more production-safe code. (For more about writing production-ready
code, see Michael Nygard'sRelease It! inResources.)
Back to top
In conclusion
The java.util.concurrent package contains many more nifty utilities that extend
well beyond Collections, particularly in the .locks and .atomic packages. Dig in and
you'll also find useful control structures like CyclicBarrier and more.
Like many aspects of the Java platform, you don't need to look very hard to find
infrastructure code that can be tremendously helpful. Whenever you're writing
multithreaded code, remember the utilities discussed in this and theprevious article.
Next time, we'll branch out into a new topic: five things you didn't know about Jars.
http://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things4.htmlhttp://www.ibm.com/developerworks/java/library/j-5things4.htmlhttp://www.ibm.com/developerworks/java/library/j-5things4.htmlhttp://www.ibm.com/developerworks/java/library/j-5things4.htmlhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconhttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#resourceshttp://www.ibm.com/developerworks/java/library/j-5things5/index.html#ibm-pconRecommended