java.util.concurrent.docx

Embed Size (px)

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/#author1
  • 7/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-pcon
  • 7/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.html
  • 7/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-pcon
  • 7/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-pcon
  • 7/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/#resources
  • 7/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-pcon
  • 7/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-pcon
  • 7/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#listing2
  • 7/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-pcon
  • 7/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-pcon