66
UNIVERSIDADE ESTADUAL DO SUDOESTE DA BAHIA CURSO DE CIÊNCIA DA COMPUTAÇÃO PROGRAMAÇÃO CONCORRENTE – 2015.1 Fábio M. Pereira ([email protected])

Programação Concorrente - Gerenciamento de Threads - Parte I

Embed Size (px)

Citation preview

Page 1: Programação Concorrente - Gerenciamento de Threads - Parte I

UNIVERSIDADE ESTADUAL DO SUDOESTE DA BAHIA CURSO DE CIÊNCIA DA COMPUTAÇÃO

PROGRAMAÇÃO CONCORRENTE – 2015.1

Fábio M. Pereira

([email protected])

Page 2: Programação Concorrente - Gerenciamento de Threads - Parte I

Roteiro

• Criando e executando uma thread

• Recuperando e atribuindo informações de uma thread

• Interrompendo uma thread

• Controlando a interrupção de uma thread

• Adormecendo e retomando uma thread

• Aguardando pela finalização de uma thread

Page 3: Programação Concorrente - Gerenciamento de Threads - Parte I
Page 4: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando e Executando Uma Thread

• Vamos aprender como criar e executar uma thread em uma aplicação Java

• Tal como acontece com todos os elementos da linguagem Java, threads são objetos

• Temos duas maneiras de criar uma thread em Java: – Estendendo a classe Thread e substituindo o método run()

– A construção de uma classe que implementa a interface Runnable e, em seguida, criar um objeto da classe Thread passando o objeto que implementa a interface Runnable como um parâmetro

• Vamos usar a segunda abordagem para criar um programa simples que cria e executa 10 threads

• Cada thread calcula e imprime a tabela de multiplicação de um número entre um e 10

Page 5: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

1. Crie um novo projeto Java

2. Crie uma classe chamada Calculadora que implemente a interface Runnable public class Calculadora implements Runnable

{

3. Declare um atributo private int chamado numero e implemente o construtor da classe inicializando o seu valor private int numero;

public Calculadora(int numero) {

this.numero=numero;

}

Page 6: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

4. Implemente o método run(), este método irá executar as instruções da thread que criamos, assim, este método irá calcular a tabela de multiplicação para o número @Override

public void run() {

for (int i=1; i<=10; i++){

System.out.printf("%s: %d * %d = %d\n",

Thread.currentThread().getName(),

numero,i,i*numero);

}

}

5. Agora implemente a classe principal da aplicação, criando uma classe Main que contém o método main() public class Main {

public static void main(String[] args) {

Page 7: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

6. Dentro do método main() crie um laço for para 10 iterações, dentro do laço crie um objeto da classe Calculadora, um objeto da classe Thread, passe o objeto Calculadora como parâmetro, e chame o método start() do objeto thread for (int i=1; i<=10; i++){

Calculadora calc=new Calculadora(i);

Thread thread=new Thread(calc);

thread.start();

}

Page 8: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Execute o programa e veja como as diferentes threads trabalham em paralelo

Page 9: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Cada programa Java tem pelo menos uma thread de execução

• Quando executamos o programa, a JVM executa essa thread de execução que chama o método main() do programa

• Quando chamamos o método start() de um objeto Thread, estamos criando uma outra thread de execução

• Nosso programa terá tantas threads de execução quanto chamadas do método start()

• Um programa Java termina quando todas as suas threads terminarem (mais especificamente, quando todas as suas threads não-daemon terminarem)

Page 10: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Se a thread inicial (aquele que executa o método main()) termina, o restante das threads irá continuar com a sua execução até que terminem

• Se uma das threads chamar a instrução System.Exit() para terminar a execução do programa, todas as threads irão terminar a sua execução

• Criar um objeto da classe Thread não cria uma nova thread de execução

• Além disso, chamar o método run() de uma classe que implementa a interface Runnable não cria uma nova thread de execução

• Apenas chamar o método start() cria uma nova thread de execução

Page 11: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Como mencionado no início, há uma outra maneira de criar uma nova thread de execução:

– Podemos implementar uma classe que estende a classe Thread

e substituir o método run() da classe

– Em seguida, podemos criar um objeto dessa classe e chamar o método start() para ter uma nova thread de execução

Page 12: Programação Concorrente - Gerenciamento de Threads - Parte I
Page 13: Programação Concorrente - Gerenciamento de Threads - Parte I

Recuperando e Atribuindo Informações de Uma Thread

• A classe Thread salva alguns atributos de informações que podem nos ajudar a identificar uma thread, saber o seu status, ou controlar a sua prioridade

• Estes atributos são: – ID: armazena um identificador único para cada Thread

– Nome: armazena o nome da Thread

– Prioridade: armazena a prioridade dos objetos Thread. Threads podem ter uma prioridade entre um e dez, onde um é a prioridade mais baixa e dez é a mais alta. Não é recomendado alterar a prioridade das threads, mas é uma possibilidade que podemos usar se quisermos

– Status: armazena o status da Thread. Em Java, Thread pode estar em um desses seis estados: new, runnable, blocked, waiting, time waiting, ou terminated

Page 14: Programação Concorrente - Gerenciamento de Threads - Parte I

Recuperando e Atribuindo Informações de Uma Thread

• Neste exemplo, vamos desenvolver um programa que estabelece o nome e prioridade para 10 threads e, em seguida, mostra informações sobre o seu estado até que elas terminem

• As threads irão calcular a tabela de multiplicação de um número

Page 15: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

1. Repita os passos de 1 a 5 do exemplo anterior para criação da classe Calculadora e do programa principal

6. Agora crie um array de 10 elementos Thread e um array com 10 elementos Thread.State para armazenar as threads que iremos executar e os seus status Thread threads[]=new Thread[10];

Thread.State status[]=new Thread.State[10];

Page 16: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

7. Crie 10 objetos da classe Calculadora, cada um inicializado com um número diferente, e 10 threads para executá-los, atribua valor máximo de prioridade a cinco delas e valor de prioridade mínimo às outras cinco for (int i=0; i<10; i++){

threads[i]=new Thread(new Calculadora(i+1));

if ((i%2)==0){

threads[i].

setPriority(Thread.MAX_PRIORITY);

} else {

threads[i].

setPriority(Thread.MIN_PRIORITY);

}

threads[i].setName("Thread "+i);

}

Page 17: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

8. Crie um objeto PrintWriter para escrever em um arquivo a evolução do status das threads try (

FileWriter file = new FileWriter( ".\\log.txt"); // "./log.txt" no Linux!

PrintWriter pw = new PrintWriter(file);) {

// O resto do programa (itens 9 a 11) vai aqui!

// ...

} catch (IOException e) { e.printStackTrace(); }

9. Escreva neste arquivo o status das 10 threads for (int i=0; i<10; i++){

pw.println("Main : Status da Thread "+i+" : “

+ threads[i].getState());

status[i]=threads[i].getState();

}

10. Inicie a execução das 10 threads for (int i=0; i<10; i++){

threads[i].start();

}

Page 18: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

11. Até que as 10 threads terminem, iremos checar os seus status, se detectarmos uma mudança no status da thread, iremos escrevê-la no arquivo boolean finish=false;

while (!finish) {

for (int i=0; i<10; i++){

if (threads[i].getState()!=status[i]) {

writeThreadInfo(pw, threads[i],status[i]);

status[i]=threads[i].getState();

}

}

finish=true;

for (int i=0; i<10; i++){

finish=finish &&

(threads[i].getState()==

Thread.State.TERMINATED);

}

}

pw.close();

Page 19: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

12. Implemente o método writeThreadInfo() que escreve a ID, nome, prioridade, status anterior e novo status da thread private static void writeThreadInfo(PrintWriter

pw, Thread thread, Thread.State state) {

pw.printf("Main : Id %d - %s\n",thread.getId(),

thread.getName());

pw.printf("Main : Prioridade: %d\n",

thread.getPriority());

pw.printf("Main : Estado anterior: %s\n",

state);

pw.printf("Main : Novo Estado: %s\n",

thread.getState());

pw.printf("Main : **********************" + "**************\n");

}

Page 20: Programação Concorrente - Gerenciamento de Threads - Parte I

Criando o Programa

• Execute o exemplo e abra o arquivo log.txt para ver a evolução das 10 threads

Page 21: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• O programa mostra no console as tabuadas calculadas pelas threads e a evolução do estado das diferentes threads no arquivo log.txt, desta forma podemos visualizar melhor a evolução das threads

• A classe Thread tem atributos para armazenar todas as informações de uma thread

• A JVM utiliza a prioridade das threads para selecionar aquela que usa a CPU em cada momento e atualiza o status de cada thread de acordo com a sua situação

• Se não especificarmos um nome para uma thread, a JVM automaticamente atribui a ela um nome com o formato, Thread-XX, onde XX é um número

• Não podemos modificar a ID ou o status de uma thread, a classe Thread não implementa os métodos setId() e setStatus() para permitir a sua alteração

Page 22: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Também podemos acessar os atributos de uma thread a partir da implementação da interface Runnable, podemos usar o método estático CurrentThread() da classe Thread para acessar o objeto Thread que está executando o objeto Runnable

• Devemos levar em conta que o método setPriority() pode lançar uma exceção IllegalArgumentException se tentarmos estabelecer uma prioridade que não está entre 1 e 10

Page 23: Programação Concorrente - Gerenciamento de Threads - Parte I
Page 24: Programação Concorrente - Gerenciamento de Threads - Parte I

Interrompendo Uma Thread

• Um programa Java com mais de uma thread de execução só termina quando a execução de todas as suas threads e, mais especificamente, quando todas as suas threads não-daemon terminam a sua execução ou quando uma das threads usam o método System.exit()

• Às vezes, vamos precisar terminar uma thread, porque queremos encerrar um programa, ou quando um usuário do programa quer cancelar as tarefas que um objeto Thread está fazendo

• Java fornece um mecanismo de interrupção para indicar a uma thread que queremos terminá-la

Page 25: Programação Concorrente - Gerenciamento de Threads - Parte I

Interrompendo Uma Thread

• Uma peculiaridade deste mecanismo é que a Thread

tem que verificar se ela foi interrompida ou não, e pode decidir se ela responde ao pedido de finalização ou não

• A Thread pode ignorá-lo e continuar com a sua execução

Page 26: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

1. Crie uma classe chamada PrimeGenerator que estende a classe Thread

public class PrimeGenerator extends Thread{

2. Sobrescreva o método run() incluindo um laço que irá rodar indefinidamente. Neste laço iremos processar números consecutivos iniciando por um. Para cada número iremos calcular se ele é primo e, neste caso, iremos imprimi-lo no console. @Override

public void run() {

long number=1L;

while (true) {

if (isPrime(number)) {

System.out.printf("O numero %d eh Primo\n",

number);

}

...

Page 27: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

3. Após processar um número, verifique se a thread foi interrompida através do método isInterrupted(). Se o método retornar true, escreveremos uma mensagem e terminaremos a execução da thread. if (isInterrupted()) {

System.out.printf("O Gerador de

Primos foi interrompido!\n");

return;

}

number++;

}

}

Page 28: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

4. Implemente o método isPrime(). Ele irá retornar um valor boolean indicando se o número recebido como parâmetro é um número primo (true) ou não (false). private boolean isPrime(long number) {

if (number <=2) {

return true;

}

for (long i=2; i<number; i++){

if ((number % i)==0) {

return false;

}

}

return true;

}

Page 29: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

5. Agora implemente a classe principal do exemplo (Main), implementando o método main(). public class Main {

public static void main(String[] args) {

6. Crie e inicie um objeto da classe PrimeGenerator. Thread task=new PrimeGenerator();

task.start();

7. Espere por 5 segundos e interrompa a thread PrimeGenerator. try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

task.interrupt();

8. Rode o programa e veja os resultados.

Page 30: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

Page 31: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• A classe Thread tem um atributo que armazena um valor booleano que indica se a thread foi interrompida ou não

• Quando chamamos o método interrupt() de uma thread, definimos esse atributo para true

• O método isInterrupted() retorna apenas o valor do atributo

• A classe Thread tem outro método para verificar se foi interrompida ou não, é o método estático, interrupted(), que verifica se a thread atual em execução foi interrompida ou não – O método interrupted(), diferentemente de isInterrupted(),

modifica o valor do atributo interrupted para false

– Por se tratar de um método estático, a sua utilização não é recomendada

Page 32: Programação Concorrente - Gerenciamento de Threads - Parte I
Page 33: Programação Concorrente - Gerenciamento de Threads - Parte I

Controlando a Interrupção de Uma Thread

• O mecanismo mostrado no exemplo anterior, pode ser utilizado se a thread que pode ser interrompida é simples, mas se a thread implementa um algoritmo complexo dividido em alguns métodos, ou se tem métodos com chamadas recursivas, podemos usar um mecanismo melhor para controlar a interrupção da thread

• Java fornece a exceção InterruptedException com esta finalidade, podemos lançar essa exceção quando detectarmos a interrupção da thread e capturá-la no método run()

Page 34: Programação Concorrente - Gerenciamento de Threads - Parte I

Controlando a Interrupção de Uma Thread

• Neste exemplo, vamos implementar uma Thread que procura arquivos com um determinado nome em uma pasta e em todas as suas subpastas para mostrar como usar a exceção InterruptedException para controlar a interrupção de uma thread

Page 35: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

1. Crie uma classe chamada FileSearch e especifique que ela implementa a interface Runnable. public class FileSearch implements Runnable {

2. Declare dois atributos privados, um para o nome do arquivo que será procurado e outro para a pasta inicial. Implemente o construtor dessa classe, que inicializa esses atributos. private String initPath;

private String fileName;

public FileSearch(String initPath, String fileName) {

this.initPath = initPath;

this.fileName = fileName;

}

Page 36: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

3. Implemente o método run() da classe FileSearch. Ele verifica se o atributo initPath é uma pasta e, se for, chama o método processDirectory(). Este método pode lançar uma exceção InterruptedException, devendo capturá-la. @Override

public void run() {

File file = new File(initPath);

if (file.isDirectory()) {

try {

directoryProcess(file);

} catch (InterruptedException e) {

System.out.printf("%s: A busca foi interrompida",

Thread.currentThread().getName());

}

}

}

Page 37: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

4. Implemente o método directoryProcess(). Este método irá obter e processar os arquivos e subpastas da pasta. Para cada subpasta, o método irá fazer uma chamada recursiva passando a pasta como parâmetro. Para cada arquivo, o método irá chamar o métodos fileProcess(). Após processar todos os arquivos e pastas, o método verifica se a Thread foi interrompida e, neste caso, lança uma exceção InterruptedException.

Page 38: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

private void directoryProcess(File file) throws

InterruptedException {

System.out.printf("Processando %s ...\n",

file.getName());

File list[] = file.listFiles();

if (list != null) {

for (int i = 0; i < list.length; i++) {

if (list[i].isDirectory()) {

directoryProcess(list[i]);

} else {

fileProcess(list[i]);

}

}

}

if (Thread.interrupted()) {

throw new InterruptedException();

}

}

Page 39: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

5. Implemente o método processFile(). Este método irá comparar o nome do arquivo que está sendo processado com o nome que estamos buscando. Se forem iguais, iremos escrever uma mensagem no console. Após esta comparação, a Thread irá verificar se foi interrompida e, neste caso, irá lançar uma exceção InterruptedException. private void fileProcess(File file) throws InterruptedException {

if (file.getName().equals(fileName)) {

System.out.printf("%s : %s !!!\n", Thread.currentThread().getName(),

file.getAbsolutePath());

}

if (Thread.interrupted()) {

throw new InterruptedException();

}

}

Page 40: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

6. Agora vamos implementar a classe principal do exemplo. Implemente a classe Main que contém o método main(). public class Main {

public static void main(String[] args) {

7. Crie e inicialize um objeto da classe FileSearch e uma Thread para executar a sua tarefa. Então inicie a execução da Thread. FileSearch searcher=new

FileSearch("C:\\","autoexec.bat");

// Modificar! Principalmente no Linux…

Thread thread=new Thread(searcher);

thread.start();

Page 41: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

8. Aguarde por 10 segundos e interrompa a Thread. try {

TimeUnit.SECONDS.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

thread.interrupt();

}

9. Execute o programa e veja os resultados.

Page 42: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

Page 43: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Neste exemplo, usamos exceções Java para controlar a interrupção da Thread

• Quando executamos o exemplo, o programa começa a passar por pastas, verificando se elas têm ou não o arquivo

• Por exemplo, se você entrar na pasta \b\c\d, o programa terá três chamadas recursivas ao método processDirectory()

• Quando se detecta que ele foi interrompido, ele lança uma exceção InterruptedException e continua a execução no método run(), não importa quantas chamadas recursivas foram feitas

• A exceção InterruptedException é lançada por alguns métodos Java relacionados com a API de concorrência, como em sleep()

Page 44: Programação Concorrente - Gerenciamento de Threads - Parte I
Page 45: Programação Concorrente - Gerenciamento de Threads - Parte I

Adormecendo e Retomando Uma Thread

• Às vezes, podemos estar interessado em interromper a execução da Thread durante um determinado período de tempo

– Por exemplo, uma thread em um programa verifica um estado de um sensor uma vez por minuto, o resto do tempo, a thread não faz nada

– Durante este tempo, a thread não utiliza recursos do computador

– Após este tempo, a thread estará pronta para continuar com a sua execução, quando a JVM escolhe-la para ser executada

• Podemos usar o método sleep() da classe Thread para este fim

• Este método recebe um número inteiro como parâmetro indicando o número de milissegundos que a thread suspende a sua execução

Page 46: Programação Concorrente - Gerenciamento de Threads - Parte I

Adormecendo e Retomando Uma Thread

• Quando o tempo de “dormência” acaba, a thread continua com a sua execução, na instrução após a chamada do método sleep(), quando a JVM lhe atribui tempo de CPU

• Outra possibilidade é a utilização do método sleep() de um elemento de enumeração TimeUnit

• Este método utiliza o método sleep() da classe Thread

para colocar a thread atual para dormir, mas ele recebe o parâmetro na unidade que ele representa e o converte para milissegundos

• O exemplo a seguir utiliza o método sleep() para mostrar a data atual a cada segundo

Page 47: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

1. Crie uma classe chamada FileClock e especifique que ela implementa a interface Runnable. public class FileClock implements Runnable {

2. Implemente o método run(). @Override

public void run() {

Page 48: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

3. Faça um laço com 10 iterações. Em cada iteração, criar um objeto Date, escrevê-lo para o arquivo, e chamar o método sleep() do atributo SECONDS da classe TimeUnit para suspender a execução da thread por um segundo. Com este valor, a thread ficará adormecida por cerca de um segundo. Como o método sleep () pode lançar uma exceção InterruptedException, temos que incluir o código para capturá-la. É uma boa prática incluir código que libera ou fecha os recursos que a thread está usando quando ela é interrompida.

Page 49: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

for (int i = 0; i < 10; i++) {

System.out.printf("%s\n", new Date());

try {

TimeUnit.SECONDS.sleep(1);

} catch (InterruptedException e) {

System.out.printf("FileClock foi

interrompido!");

}

}

}

Page 50: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

4. Crie uma classe chamada FileMain que contém o método main(). public class FileMain {

public static void main(String[] args) {

5. Crie um objeto da classe FileClock e a thread para executá-lo. Então, inicie a execução da Thread. FileClock clock=new FileClock();

Thread thread=new Thread(clock);

thread.start();

Page 51: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

6. Chame o método sleep() do atributo SECONDS da classe TimeUnit na Thread principal para esperar por 5 segundos. try {

TimeUnit.SECONDS.sleep(5);

} catch (InterruptedException e) {

e.printStackTrace();

};

7. Interrompa a thread FileClock. thread.interrupt();

8. Execute o exemplo e veja os resultados.

Page 52: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Quando executamos o exemplo, podemos ver como o programa escreve um objeto Date por segundo e, em seguida, a mensagem indicando que a thread FileClock

foi interrompida é mostrada

Page 53: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Quando chamamos o método sleep(), a Thread deixa a CPU e para a sua execução por um período de tempo

• Durante este tempo, ela não está consumindo tempo de CPU, de modo que o CPU pode executar outras tarefas

• Quando a Thread está dormindo e é interrompida, o método gera uma exceção InterruptedException imediatamente e não espera até que a hora de inatividade acabe

• A API de concorrência Java tem outro método que faz com que um objeto Thread deixe a CPU, é o método yield(), que indica à JVM que o objeto Thread pode liberar a CPU para outras tarefas, A JVM não garante que ele irá cumprir com este pedido

• Normalmente, ele é usado apenas para fins de depuração

Page 54: Programação Concorrente - Gerenciamento de Threads - Parte I
Page 55: Programação Concorrente - Gerenciamento de Threads - Parte I

Aguardando Pela Finalização de Uma Thread

• Em algumas situações, temos que esperar pela finalização de uma thread

• Por exemplo, podemos ter um programa que começará inicializando os recursos que necessita antes de prosseguir com o resto da execução

• Podemos executar as tarefas de inicialização como threads e aguardar sua finalização antes de continuar com o resto do programa

• Para isso, podemos usar o método join() da classe Thread

• Quando chamamos este método usando um objeto thread, ele suspende a execução da thread de chamada até que o objeto chamado termine a sua execução

Page 56: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

1. Crie uma classe chamada DataSourcesLoader e especifique que ela implementa a interface Runnable. public class DataSourcesLoader implements

Runnable {

2. Implemente o método run(). Ele escreve uma mensagem para indicar que iniciou a sua execução, espera por 4 segundos, e escreve uma outra mensagem para indicar que finalizou a sua execução.

Page 57: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

@Override

public void run() {

System.out.printf("Iniciando a carga de

recursos: %s\n",new Date());

try {

TimeUnit.SECONDS.sleep(4);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.printf(“Carga de recursos

finalizada: %s\n",new Date());

}

Page 58: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

3. Crie uma classe chamada NetworkConnectionsLoader

e especifique que ela implementa a interface Runnable. Implemente o método run(). Será igual ao método de run() da classe DataSourceLoader, mas esta vai adormecer durante 6 segundos.

4. Agora crie uma classe chamada Main que contenha o método main(). public class Main {

public static void main(String[] args) {

Page 59: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

5. Crie um objeto da classe DataSourcesLoader e uma Thread para executá-lo. DataSourcesLoader dsLoader = new

DataSourcesLoader();

Thread thread1 = new

Thread(dsLoader,"DataSourceThread");

6. Crie um objeto da classe NetworkConnectionsLoader

e uma Thread para executá-lo. NetworkConnectionsLoader ncLoader = new

NetworkConnectionsLoader();

Thread thread2 = new

Thread(ncLoader,

"NetworkConnectionThread");

Page 60: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

7. Chame o método start() dos dois objetos Thread. thread1.start();

thread2.start();

8. Aguarde a finalização de ambos os segmentos usando o método join(). Este método pode lançar uma exceção InterruptedException, por isso temos de incluir o código para capturá-la. try {

thread1.join();

thread2.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

Page 61: Programação Concorrente - Gerenciamento de Threads - Parte I

Programa Exemplo

9. Escreva uma mensagem para indicar o fim do programa. System.out.printf("Main: A configuracao foi

carregada: %s\n",new Date());

10. Execute o programa e veja os resultados.

Page 62: Programação Concorrente - Gerenciamento de Threads - Parte I

Funcionamento...

• Quando executarmos este programa, podemos ver como os dois objetos de Thread iniciam a sua execução

• Em primeiro lugar, a thread DataSourcesLoader termina a sua execução

• Em seguida, a classe NetworkConnectionsLoader

termina a sua execução e, naquele momento, o objeto Thread principal continua sua execução e escreve a mensagem final

Page 63: Programação Concorrente - Gerenciamento de Threads - Parte I

O Método join()

• Java fornece duas formas adicionais do método join():

– join (long milissegundos)

– join (long milissegundos, long nanos)

• Na primeira versão do método join(), em vez de esperar indefinidamente pela finalização da thread chamada, a thread que faz a chamada aguarda os milissegundos especificados como um parâmetro do método

• Por exemplo, se o objeto thread1 tem o código, thread2.join(1000), a thread thread1 suspende a sua execução, até que uma destas duas condições seja verdadeira: – thread2 termina a sua execução

– 1.000 milissegundos tenham passado

Page 64: Programação Concorrente - Gerenciamento de Threads - Parte I

O Método join()

• A segunda versão do método join() é similar à primeira, mas recebe o número de milissegundos e o número de nano segundos como parâmetros

Page 65: Programação Concorrente - Gerenciamento de Threads - Parte I

Referências

• González, J. F. Java 7 Concurrency Cookbook. Pack Publishing, 2012.

Page 66: Programação Concorrente - Gerenciamento de Threads - Parte I

UNIVERSIDADE ESTADUAL DO SUDOESTE DA BAHIA CURSO DE CIÊNCIA DA COMPUTAÇÃO

PROGRAMAÇÃO CONCORRENTE – 2015.1

Fábio M. Pereira

([email protected])