Você está na página 1de 12

Threads em Java

Miguel Jonathan- DCC/IM e NCE/UFRJ


atualizado em 16/11/2011

Conceitos:
Diferena entre processo e thread:
Um processo um programa em execuo que possui o seu prprio espao de endereamento.
Um sistema operacional multitarefa capaz de controlar a execuo de mais de um processo
ao mesmo tempo, de forma concorrente, fazendo a CPU alternar a execuo das instrues de
cada processo.
Uma thread um fluxo sequencial de controle, ou linha de execuo, dentro de um processo
ou programa. Um processo pode assim ter diversas threads executando concorrentemente,
mas todas partilhando o mesmo espao de endereamento. Como no h necessidade de
trocar de contexto, as threads representam uma forma mais leve de processamento
concorrente.
A Mquina Virtual Java (JVM) permite que uma aplicao tenha diversas linhas de execuo
rodando concorrentemente. H sempre pelo menos uma thread, que roda o mtodo main().
Essa thread criada automaticamente, e outras podem ser criadas pelo programador. O
programa gc (garbage collector) roda em outra thread tambm iniciada pela JVM.
Porque usar threads em aplicaes:
Threads tm vrias utilidades, especialmente quando o uso de um recurso do programa pode
demandar muito tempo, e travar outras tarefas que esto aguardando, ou quando se precisa
ficar verificando a ocorrncia de algum evento para efetuar alguma ao. Nesse ltimo caso,
uma thread pode ficar dedicada apenas para verificar periodicamente a ocorrncia do evento.
A aplicao mais usual a interao com as interfaces grficas (menus, botes) quando se
quer obter resposta quase que imediata a uma ao.
A classe java.lang.Thread:
Em Java, cada thread implementada como um objeto, que deve ser uma instncia de uma
subclasse de java.lang.Thread criada para esse fim.
A interface java.lang.Runnable
Essa interface obriga a ter o mtodo public void run(). Toda thread criada para executar
os comandos de algum mtodo com essa assinatura. A prpria classe Thread possui esse
mtodo, mas vazio, ou seja, no faz nada.
Como criar uma thread:
H duas formas bsicas para se criar uma thread:
a) Criar uma subclasse explcita de java.lang.Thread, e redefinir o mtodo run()com os
comandos que a thread dever executar.
Ex:
class MinhaThread extends Thread{
public void run(){
<instrues da thread>
}
}
A partir da possvel criar quantas instncias se desejar dessa classe. Cada vez que
enviar a mensagem start() para uma instncia, uma nova linha de execuo ser iniciada
com os comandos do mtodo run(), que rodar em paralelo com as outras threads:
MinhaThread t = new MinhaThread();
t.start();
ou, simplesmente:
new MinhaThread().start();

Note que no se pode enviar a mensagem run() diretamente para um objeto Thread.
Envia-se a mensagem start(), que criar a thread onde rodaro os comandos do mtodo
run().
Obs: Threads podem ser criadas sem referncia explcita, como na forma mais simples
acima ( ex: new MinhaThread().start();) , sem risco de serem removidas pelo Garbage
Collector, pois possuem uma referncia interna que permanece at o mtodo run()
associado terminar.

b) A segunda forma de criar thread recomendada em situaes onde queremos executar um


mtodo de uma classe qualquer em uma thread separada, sem que essa classe herde de
Thread. Isso necessrio no caso da classe j ser uma subclasse de outra, pois no
poderia herdar tambm de Thread. Nesse caso, fazemos a classe em questo implementar
a interface Runnable e colocamos no mtodo public void run() os comandos que sero
executados na thread.
No exemplo abaixo, um mtodo run() da classe X ser colocado em uma thread:
class X implements Runnable{
public void run(){
<instrues da thread>
}
..... outros mtodos de X, construtores, atributos, etc
}
A seguir, em outro mtodo, criamos uma instncia de X, e passamos a instncia como
argumento do construtor da classe Thread:
X x = new X(...);
Thread t = new Thread(x);
O efeito disso a criao de uma instncia de Thread que executar o mtodo run()
definido na classe do argumento do construtor.
Enviando a seguir a mensagem start() para a thread far iniciar uma nova linha de
execuo com os comandos do mtodo run() da classe X, que rodar em paralelo com as
outras threads.
t.start();
Nome da thread:
Toda thread tem um nome (uma string) para poder ser identificada. O nome pode ser passado
como um parmetro do construtor, e pode ser recuperado enviando para a thread a
mensagem getName(). Se um nome no for especificado no construtor, um novo nome ser
gerado automaticamente para a thread.
Como incluir o nome na chamada do construtor:
//subclasse explicita de Thread:
Thread t1 = new MinhaThread("Thread 1");
// usando instancia de classe X que implementa Runnable:
Thread t2 = new Thread(new X(), "Thread 2");
Prioridade:
Cada thread possui uma prioridade. Threads com prioridades mais elevadas so executadas
preferencialmente antes de threads com menor prioridade. A prioridade default 5 (em uma
escala de 1 a 10), mas pode ser alterada enviando a mensagem setPriority(int) para a
thread. (Nota: na classe Thread existem as constantes static MAX_PRIORITY, MIN_PRIORITY e
NORM_PRIORITY, com valores 10, 0 e 5, mas que podem variar dependendo da
implementao).

Quando existem diversas threads de mesma prioridade sendo executadas, Java aloca um
tempo mximo para processar os comandos de cada uma, aps o que interrompe a thread em
execuo e passa a processar os comandos da seguinte.
O mtodo de classe Thread.currentThread():
Esse mtodo permite acessar a thread que est executando no momento em que chamado.
usado dentro do mtodo run() para permitir identificar e/ou alterar os parmetros da thread
(lembre-se que o run() pode ser de outra classe). Por exemplo, para imprimir o nome da
thread onde esse comando est executando:
System.out.println(Thread.currentThread().getName());
Fazendo uma thread dormir por um certo tempo:
O mtodo de classe Thread.sleep(long milisseg) permite interromper a execuo da thread
pelo tempo dado no argumento.
Deve ser usado dentro de um bloco try porque, caso a thread receba uma mensagem
interrupt() enquanto estiver parada por um sleep(), ser lanada uma
InterruptedException.
Cedendo o tempo de processamento para outras threads:
Uma thread pode ceder o restante do tempo de processamento alocado a ela, executando o
comando yield(). O controle passa para a prxima thread que estiver aguardando. Evita
desperdiar tempo de processamento.
Exemplos:
Os exemplos abaixo simulam uma corrida entre dois times, Flamengo e Botafogo.
Nestes dois exemplos, duas threads escrevem em paralelo na console os nmeros de 1 a 99,
seguido do nome do time.
1. No primeiro exemplo, uma subclasse de Thread definida, onde o seu mtodo run() simula
a corrida. Duas instncias dessa classe so criadas para representar os dois jogadores.
Cada thread recebe o nome de um time (Flamengo e Botafogo) passado pelo construtor.
Para tornar o resultado aleatrio, e possibilitar uma melhor observao dos resultados,
cada thread dorme uma quantidade aleatria de milisegundos entre 0 e 299 antes de
imprimir a prxima linha. Para isso usado o mtodo esttico sleep(long miliseg) da classe
Thread.
Antes de terminar, cada thread imprime a palavra TERMINOU, seguido do seu nome. O
mtodo getName() da classe Thread retorna a string com o nome.
public class ThreadSimples extends Thread {
public ThreadSimples(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i + " " + getName());
try {
sleep((long)(Math.random() * 300));
}
catch (InterruptedException e) {}
}
System.out.println("TERMINOU " + getName()+"!");
}
}
public class TesteDuasThreads {
public static void main (String[] args) {
ThreadSimples bota = new ThreadSimples("BOTAFOGO");
bota.setPriority(4);
ThreadSimples mengo =new ThreadSimples("FLAMENGO");
mengo.setPriority(6);
mengo.start();

bota.start();
System.out.println("Main terminado!");
}
}

2.

O segundo exemplo essencialmente o mesmo que o primeiro, s que nesse caso no


se cria nenhuma subclasse de Thread.
Em vez disso uma classe Time definida, que implementa a interface Runnable. O
mtodo run() de Time contm os mesmos comandos que o mtodo run() da subclasse
de Thread do primeiro exemplo. Nesse caso, a prioridade de cada thread passada pelo
construtor do time.
public class Time implements Runnable {
String nome;
int priority;
public Time(String nome, int priority) {
this.nome=nome;
this.priority=priority;
}
public void run() {
Thread.currentThread().setPriority(priority);
for (int i = 0; i < 100; i++) {
System.out.println(i + "R " + nome);
try {
Thread.sleep((long)(Math.random() * 300));
}
catch (InterruptedException e) {}
}
System.out.println("TERMINOU " + nome+"!");
}

}
public class TesteDuasThreads {
public static void main (String[] args) {
Time bota = new Time("BOTAFOGO",1);
Time mengo =new Time("FLAMENGO",7);
new Thread(mengo).start();
new Thread(bota).start();
System.out.println("Main terminado!");
}
}

Interrupo de uma Thread


Toda thread tem uma varivel interna, um flag binrio, que contm o seu "estado de
interrupo" (interrupt status).
Esse flag fica "setado", ou seja, valendo 1, se a thread recebeu uma solicitao para ser
interrompida, por meio da mensagem interrupt().
Essa mensagem no para a thread automaticamente. A prpria thread deve avaliar o que fazer
e como se terminar.
O caso tpico a thread fazer alguma finalizao e executar return, para se terminar.
Caso a thread esteja bloqueada temporariamente por ter executado um sleep(), join() ou
wait(), ela receber tambm uma InterruptedException ao receber a mensagem
interrupt(). Nesse caso, ser obrigatrio haver blocos try-catch para essa exceo
verificada, e o bloco catch poder fazer o tratamento da interrupo. caso do primeiro
exemplo mostrado a seguir.
No caso da thread no incluir comandos que podem lanar InterruptedException, a thread
pode checar se o seu status de interrupo foi "setado" por meio de uma chamada ao mtodo
static boolean interrupted()da classe Thread. Esse mtodo de classe verifica o status da

thread que est executando (a current thread), retornando true se o status for 1, e false em
caso contrrio.
A execuo desse mtodo tambm resseta automaticamente o status de interrupo para
zero.
Exemplos:
As classes abaixo mostram o uso de interrupo nos dois casos. Uma thread separada da
thread main() fica imprimindo indefinidamente na console os mltiplos de um valor raiz. A
impresso deve ser interrompida quando a tecla ENTER do teclado for acionada dentro do
mtodo main.
As classes devem ser usadas aos pares. O mtodo main() dispara a thread e fica aguardando
a entrada do teclado, com o comando br.readLine(). Em seguida, envia para a thread a
mensagem interrupt().
No primeiro caso, a thread usa o mtodo Thread.sleep(1) para "dormir" 1 milissegundo entre
cada impresso. O bloco catch pega a interrupo e termina a thread com return.
No segundo caso, no usado o sleep(), e por isso no existem blocos try-catch para
detectar a interrupo. O mtodo Thread.interrupted() usado para checar, a cada volta do
lao de impresso, se o status de interrupo mudou para 1.
a) Interrupo de thread por meio de InterruptedException (thread tem sleep()):
public class ImprimeThreadComSleep extends Thread{
private int raiz;
public ImprimeThreadComSleep(int raiz){
this.raiz = raiz;
}
public void run(){
int i=1;
int n=raiz;
while(true){
System.out.println(n= raiz*i);
i++;
try{
sleep(1);
}
catch(InterruptedException e){
System.out.println ("Thread interrompida enquanto dormia!");
return; // termina a thread
}
}
}
}
import java.io.*;
public class InterrompeThread1 {
public static void main(String[]args){
ImprimeThreadComSleep t;
if (args.length < 1){
System.out.println("Este programa necessita de um argumento inteiro, a raiz");
return;
}
else {
try{
int raiz = Integer.parseInt(args[0]);
t = new ImprimeThreadComSleep(raiz);
t.start();
}catch(NumberFormatException nf){
System.out.println("Este programa necessita de um argumento inteiro");
return;
}

}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try{
br.readLine(); // aguarda digitar ENTER
}
catch (IOException e) {}
t.interrupt();
} // main termina
}

b) Interrupo de thread por meio de Thread.interrupted() (thread sem sleep()):


public class ImprimeThreadSemSleep extends Thread {
private int raiz;
public ImprimeThreadSemSleep(int raiz) {
this.raiz = raiz;
}
public void run() {
int i = 1, n = raiz;
while (true) {
System.out.println(n = raiz * i);
i++;
if (Thread.interrupted()) {
System.out.println("Thread interrompida sem estar dormindo!");
return;
}
}
}
}
import java.io.*;
public class InterrompeThread2 {
public static void main(String[]args){
ImprimeThreadSemSleep t;
if (args.length < 1){
System.out.println("Este programa necessita de um argumento inteiro, a raiz");
return;
}
else {
try{
int raiz = Integer.parseInt(args[0]);
t = new ImprimeThreadSemSleep(raiz);
t.start();
}
catch(NumberFormatException nf){
System.out.println("Este programa necessita de um argumento inteiro");
return;
}
}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try{
br.readLine(); // aguarda digitar ENTER
}
catch (IOException e) {}
t.interrupt();
}// main termina
}

Uso Concorrente de Recursos


Consiste na tentativa de uso simultneo de um recurso por mais de um processo: ex: dois
carros tentando estacionar na mesma vaga, duas pessoas tentando passar pela mesma porta,
dois processos tentando imprimir na mesma impressora, duas threads tentando acessar uma
mesma rea da memria. importante evitar essas "colises". preciso ento garantir que
um recurso ficar disponvel para acesso por apenas uma thread de cada vez. Isso

conseguido em Java marcando, com uma sinalizao de "tranca" ou "lock", a parte de cdigo
em que a thread faz uso de um recurso partilhado com outras threads.
O atendimento s threads que disputam um mesmo recurso no feito exatamente na forma
de uma fila de espera, pois o escalonador da JVM no muito determinstico, embora possa
seguir sugestes dadas por comandos como yield() e setPriority(). Java usa o mecanismo
de semforos.
Semforo (ou monitor, lock/tranca) e a palavra-chave synchronized.
Um semforo um sinalizador associado a um recurso que monitorado para ser usado por
uma nica thread de cada vez. O recurso sempre associado a um objeto. Todo objeto em
Java contm uma nica "tranca", que partilhada por todos os mtodos sincronizados desse
objeto.. Se o valor do semforo for zero, o objeto est disponvel.
Em Java, esse mecanismo implementado com o uso da palavra-chave synchronized para
prefixar um mtodo que deve rodar em uma thread com uso exclusivo do objeto que ativou o
mtodo. Uma thread, ao entrar em um mtodo sincronizado de um objeto, toma posse e
incrementa o semforo do objeto, impedindo outras threads de entrarem em outros mtodos
sincronizados da mesma classe, at a thread que detm a tranca terminar de executar o
mtodo.
Ao sair de um mtodo sincronizado, a thread decrementa o semforo do objeto, que ficar
liberado para uso por outras threads sincronizadas, quando o valor do semforo voltar a zero
(uma mesma thread, aps adquirir o semforo de um objeto, pode entrar em vrios mtodos
sincronizados do mesmo objeto, e cada vez que isso ocorre o semforo ser incrementado
mais uma vez).
Quando uma thread executa um mtodo sincronizado m(), que foi ativado a partir de um
determinado objeto x, como em x.m(), o acesso ao objeto x fica bloqueado a todas as demais
threads que tentarem executar esse ou outros mtodos sincronizados da classe de x, at que o
mtodo m() termine e libere a tranca.
Podemos tambm restringir o acesso a apenas um bloco de cdigo dentro de um mtodo,
prefixando o bloco com a palavra synchronized, com um objeto entre parnteses:
Ex: synchronized(x) {
<bloco de cdigo>
}
Essa construo obriga a que a tranca do objeto x deva ser adquirida por uma thread para
executar o bloco, e enquanto a tranca no for liberada por essa thread, nenhuma outra poder
executar esse bloco para esse objeto.
Trancas de Classes:
Classes tambm so objetos, e possuem trancas. A tranca de uma classe se refere aos seus
mtodos estticos sincronizados (synchronized static), e quando uma thread executa um
mtodo esttico sincronizado, o acesso s variveis de classe fica bloqueado para outras
threads.
Liberando a tranca do objeto com o wait():
De dentro de um mtodo ou bloco sincronizado, o envio da mensagem wait()ao objeto que
ativou o mtodo (this) suspende a execuo da thread, e libera a tranca desse objeto.
A chamada para wait() pode no ter argumento (forma mais usada, espera indeterminada)
ou ter um valor de tempo de espera determinado em milissegundos. A execuo do mtodo
ficar suspensa (e a thread entra no estado bloqueado) at que o tempo se esgote, ou at que
uma outra thread dispare um mtodo notify() ou notifyAll(). Nesse momento, a thread

em espera acorda e retoma ao estado "runnable", passando a poder receber tempo de


processamento. Tipicamente, essa thread aguarda que uma condio externa mude (em geral
por conta da ao de outras threads).
Exemplo de uso de threads com sincronismo
(Adaptado de um exemplo de Paulo Csar M. Jeveaux em www.portaljava.com.br)
Nesse exemplo, um banco tem 10 contas.
Cada conta criada com um valor inicial de 10.000 reais.
So ento criadas 10 threads, uma para cada conta, e as 10 threads passam a executar seus
mtodos run() em paralelo, com igual prioridade.
Cada thread fica continuamente transferindo uma quantia aleatria (menor que 5000) para
uma outra das 9 contas, escolhida tambm aleatoriamente. Como no haver depsitos ou
saques externos, o total do dinheiro no banco (a soma dos saldos das 10 contas) deveria ficar
constante em 100.000 reais.
Para fazer uma transferncia, cada thread executa duas operaes em sequncia, em um
mtodo transfere():
a) tenta debitar da sua conta (se houver saldo) uma quantia de dinheiro escolhida
aleatoriamente, at 5000 reais; e
b) aps conseguir debitar, credita a mesma quantia em outra conta escolhida tambm
aleatoriamente.
As duas aes conjuntas, dbito de uma conta, e crdito na outra conta, formam o que se
chama uma transao atmica, no sentido de que deve ser indivisvel. Ou seja, ela no deve
ser interrompida no meio, antes que outras aes manipulem (leiam ou alterem) os valores
das contas, ou resultados estranhos podem ocorrer, como veremos a seguir.
Cada thread entra num lao em que testa se a conta tem saldo suficiente para debitar a
quantia a transferir e, no tendo, dorme por 5 milisegundos antes de testar novamente. A
ideia que, em algum momento, depsitos tero sido feitos aleatoriamente que levem o saldo
a ser suficiente para realizar a transferncia.
Esse exemplo tem duas verses:
1)

Na primeira verso, sem sincronizao, no h garantia que o mtodo transfere()


completar as duas transferncias antes que outra thread possa acessar a rea de
memria das contas do banco:
Nesta verso, as 10 threads competem por ciclos de CPU sem qualquer restrio para
acessar os valores das contas. Ocorre que a mquina virtual Java (JVM) pode a qualquer
momento interromper a execuo de uma thread e passar o controle para outra, estando
essa execuo em qualquer instruo (basta ter terminado a execuo de um bytecode).
Nessa verso, pode ocorrer que uma ou mais transaes no tenham terminado (digamos,
s foi feito o dbito, mas ainda no foi feito o crdito subsequente) antes de passar o
controle para outra thread que calcula a soma dos valores das contas. Evidentemente que,
nesse caso, a soma poder dar um resultado errado, pois deveria ser feita somente depois
que todos os crditos forem realizados.

2) Na segunda verso, foramos que o mtodo transfere() da classe Banco tenha que ser
realizado completamente (de forma atmica) por uma thread, antes de permitir que outra
thread possa assumir o controle do recurso manipulado, no caso o vetor das contas. Isso
feito prefixando o mtodo com a palavra-chave synchronized. Durante a execuo de um

mtodo sincronizado, a partir da chamada por um objeto, como em b.transfere(), a


thread passa a possuir o monitor (a tranca, ou lock) do objeto que ativou o mtodo, no
caso o banco b. Isso significa que somente essa thread pode acessar variveis de instncia
ou de classe desse objeto, at que termine, ou libere voluntariamente o monitor com uma
chamada de wait().
Dentro de um mtodo sincronizado, caso ocorra a necessidade de aguardar algum tempo
para iniciar a transao atmica, e para no manter as demais threads esperando,
possvel enviar o comando wait() para o objeto que ativou esse mtodo. O efeito
bloquear essa thread e liberar o monitor ( i.e., a tranca) para que o escalonador de tarefas
escolha outra thread para assumi-lo. A thread ficar bloqueada at que o objeto receba a
mensagem notify() ou notifyAll(), que desbloqueia as threads em estado de bloqueio
por wait.
A diferena entre os dois casos que notify() s desbloqueia uma das threads que
estava em wait, que escolhida arbitrariamente, enquanto que notifyAll() desbloqueia
todas. Depois de desbloqueada, a thread passa a competir com as demais que esto ativas
pela posse do monitor, e s depois de receb-la que voltar a executar.

Observaes:
a) Os mtodos wait(), notify(), e notifyAll() s podem ser chamados de dentro de um
bloco sincronizado. Se isso no for feito, o compilador no reclama, mas em tempo de
execuo ocorrer uma exceo do tipo IllegalMonitorStateException.
b) As chamadas de wait() devem ser feitas sempre dentro de um lao que testa a condio
para permanecer em wait, e devem estar dentro de um bloco try-catch para capturar uma
InterruptedException. Essa exceo pode ocorrer se a thread em questo receber uma
mensagem interrupt() enquanto estiver em wait, aguardando um notify().
c)

Os mtodos wait(), notify()e notifyAll() so definidos na classe Object. Ou seja,


todo e qualquer objeto pode ser sincronizado e ter um monitor associado, e receber essas
mensagens.

Implementao do exemplo:
Primeiro caso: sem usar sincronizao:
public class Banco {
public static final int VALOR_TOTAL = 10000; // total de cada conta
public static final int NUM_CONTAS = 10;
// nmero de contas no banco
private long conta[];
// array que armazena os valores de cada conta
private int transferencias;
// nmero de transferncias bancrias
public Banco() {
conta = new long[NUM_CONTAS];
for(int i = 0; i < NUM_CONTAS; i++) {
conta[i] = VALOR_TOTAL;
}
transferencias = 0;
teste();
}
public void transfere(int de, int para, int quantia) {
while(conta[de] < quantia) {
try {
Thread.sleep(5);
}catch(InterruptedException e) {}

}
conta[de] -= quantia;
try {
Thread.sleep(1); // para aumentar a chance da thread parar no meio
}catch(InterruptedException e) {}
conta[para] += quantia;
transferencias++;
if(transferencias % 5000 == 0)

teste();

}
public void teste() {
long soma = 0;
for(int i = 0; i < NUM_CONTAS; i++) soma = soma + conta[i];
System.out.println("No.de transaes: " + transferencias + " Soma: " +
soma);
}
} // fim da classe Banco
public class BancoSemSincronismo {
public static void main(String[] args) {
Banco b = new Banco();
for(int i=0; i < Banco.NUM_CONTAS; i++) {
new Transferencia(b, i).start();
}
}
}
public class Transferencia extends Thread {
private Banco b;
private int de;
public Transferencia(Banco b, int de) {
this.b = b;
this.de = de;
}

public void run() {


int para;
while(true) {
do{
para = (int)(Banco.NUM_CONTAS * Math.random());
} while(para==de);
int quantia = 1+(int)(Banco.VALOR_TOTAL * Math.random()) /2;
b.transfere(de, para, quantia);
try {
sleep(1);
}
catch(InterruptedException e) {}
}
}

Segundo caso: Usando sincronizao:

class Banco{
public static final int VALOR_TOTAL = 10000;
//Total de cada conta
public static final int NUM_CONTAS = 10;
//Nmero de contas no banco
private long conta[];
//Array que armazena o valor das contas
private int transferencias;
//indica o nmero de transferncias bancrias
public Banco() {
conta = new long[NUM_CONTAS];
for(int i = 0; i < NUM_CONTAS; i++) {
conta[i] = VALOR_TOTAL;
}
transferencias = 0;
teste();
}
public synchronized void transfere(int de, int para, int quantia) {
while(conta[de] < quantia) {
try {
wait();
}catch(InterruptedException e) {}
}
conta[de] -= quantia;
try {
Thread.sleep(1); // para aumentar a chance da thread parar no meio
}catch(InterruptedException e) {}
conta[para] += quantia;
transferencias++;
if(transferencias % 3000 == 0)
notify();

teste();

}
public void teste() {
long soma = 0;
for(int i = 0; i < NUM_CONTAS; i++)
soma += conta[i];
System.out.println("Transaes: " + transferencias + "
}
} // fim da classe Banco
public class BancoComSincronismo {
public static void main(String[] args) {
Banco b = new Banco();
for(int i=0; i < Banco.NUM_CONTAS; i++) {
new Transferencia(b, i).start();
}
}
}
public class Transferencia extends Thread {
private Banco b;
private int de;
public Transferencia(Banco b, int de) {
this.b = b;

Soma: " + soma);

this.de = de;
}

public void run() {


int para;
while(true) {
do{
para = (int)(Banco.NUM_CONTAS * Math.random());
}while(para==de);
int quantia = 1+(int)(Banco.VALOR_TOTAL * Math.random()) /2;
b.transfere(de, para, quantia);
try {
sleep(1);
}
catch(InterruptedException e) {}
}
}

Referncias:
Bruce Eckel, Thinking in Java, 3rd Edition, disponvel em:
http://www.ibiblio.org/pub/docs/books/eckel/TIJ-3rd-edition4.0.zip
Sun Java Tutorial parte dedicada a Threads e processos concorrentes:
Concurrency: http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html

Você também pode gostar