690 likes | 796 Views
JAVA MULTITHREADING TECHNIQUES. PROGRAMAÇÃO PARALELA ÚLTIMA PARTE. PRIMEIRA LINGUAGEM DE PROGRAMAÇÃO A DISPONIBILIZAR PRIMITIVAS DE CONCORRÊNCIA:. LINGUAGEM ADA (Departamento de Defesa do USA) Pouco difundida e utilizada nas Universidades e Empresas.
E N D
JAVA MULTITHREADINGTECHNIQUES PROGRAMAÇÃO PARALELA ÚLTIMA PARTE
PRIMEIRA LINGUAGEM DE PROGRAMAÇÃO A DISPONIBILIZAR PRIMITIVAS DE CONCORRÊNCIA: LINGUAGEM ADA (Departamento de Defesa do USA) Pouco difundida e utilizada nas Universidades e Empresas JAVA : É A ÚNICA LING DE USO GERAL E POPULAR QUE TORNOU AS PRIMITIVAS DE CONCORRÊNCIA DISPONÍVEIS PARA PROGRAMADORES DE APLICATIVOS. C, C++, DELPHI : SÃO CHAMADAS LINGUAGENS DE UMA ÚNICA THREAD. FAZEM CHAMADAS A PRIMITIVAS DE MULTITHREADING DO SISTEMA OPERACIONAL
CLASSE THREAD (PACOTE: JAVA.LANG) VÁRIOS CONSTRUTORES: public Thread ( String threadnome), constrói um objeto Thread cujo nome é threadnome. public Thread(), constrói um Thread cujo nome é: Thread-(1, 2, 3, ... ) VÁRIOS MÉTODOS: RUN ( O CÓDIGO DA THREAD PROPRIAMENTE DITO É SOBRESCRITO NESSE MÉTODO) START (DISPARA UMA THREAD CHAMANDO O MÉTODO RUN E RETORNA PARA O SEU CHAMADOR IMEDIATAMENTE)
OUTROS MÉTODOS: INTERRUPT, ISALIVE, YIELD, SETNAME, GETNAME
POR QUE JAVA ? ? ? LIVRE ORIENTADA A OBJETOS PORTABILIDADE API RIQUÍSSIMA: BD, I/O, REDES, ETC. VASTÍSSIMA DOCUMENTAÇÃO
SOLUÇÃO JAVA PARA PORTABILIDADE EXECUTAVEL JVM (.CLASS) PROGRAMA FONTE (.JAVA) INDEPENDENTE PLATAFORMA DEPENDENTE PLATAFORMA SOLARIS JAVAC LINUX WINDOWS IBM , XPTO
CRIANDO UMA THREAD: • EXTENDS THREAD • IMPLEMENTS RUNNABLE • package java.lang;public interface Runnable { public abstract void run();}
class TpThread extends Thread { private int t; public TpThread (int thr) { t = (int) (Math.random()* 5000 ); System.out.println("A Thread:"+thr+"dormirá:"+t); } public void run() { try { sleep ( t ); System.out.println("Thread:"+thr+ "acordando"); } catch (InterruptedException erro ) { System.out.println( erro); } } }
public class TestaThreads { public static void main ( String args[]) { TpThread t1, t2, t3, t4; t1 = new TpThread ( 1 ); t2 = new TpThread ( 2 ); t3 = new TpThread ( 3 ); t4 = new TpThread ( 4 ); System.out.println( " \nStartando as Threads" ); t1.start(); t2.start(); t3.start(); t4.start(); System.out.println( " \nThreads Startadas\n" ); } }
class TpThreadRun implements Runnable { private int t; public TpThreadRun (int th) { t = (int) (Math.random() * 5000 ); System.out.println(" Tempo para : "+th+” “+ t ); } public void run() { try { sleep ( t ); } catch (InterruptedException erro ) { System.out.println( erro); } System.out.println(" Thread:”+th+” acordando"); } }
public class Testa { public static void main ( String args[]) { TpThreadRun t1, t2, t3, t4; Thread th1, th2, th3, th4; t1 = new TpThreadRun(); t2 = new TpThreadRun(); t3 = new TpThreadRun(); t4 = new TpThreadRun(); th1 = new Thread ( t1 ); th2 = new Thread ( t2 ); th3 = new Thread ( t3 ); th4 = new Thread ( t4 ); System.out.println( " \nStartando as Threads" ); th1.start(); th2.start(); th3.start(); th4.start(); System.out.println( " \nThreads Startadas\n" ); } }
CICLO DE VIDA DE UMA THREAD NASCIMENTO START CONCLUSÃO DO I/O PRONTO NOTIFY OU NOTIFYALL DESPACHA QUANTUM FIM BLOQUEADO RODANDO INICIO DO I/O WAIT SLEEP COMPLETO ESPERANDO TEMPO FIM MORTO DORMINDO
Th01 tenta novamente Th01 compete com outras blockeds no mesmo obj Th01 blocked Th01 é selecinado para ter o lock Th01 não obtem lock do obj Lock ganho por outra thX Th01 calls um metodo synchronized Th01 exec metodos antes do wait () start Th01 obtem lock do obj Th01 chama wait() Th01 exec metodos apos wait () Th01 no conjunto das wait Th01 compete com ths pelo lock Th01 termina deixa o obj. ThX call notify() Th01 não é o escolhido Th01 não consegue Th01 requer lock do obj Th01 compete no conj. wait Th01 blocked Th01 é o escolhido
wait( c1 ) signal (c1)
objeto monitor thread monitor thread objeto monitor monitor thread thread objeto
public class Cabine { private int ncab; public Cabine ( int n ) { ncab = n; } public synchronized void Pega() { try { while ( ncab == 0 ) wait(); ncab--; } catch ( Exception e ){} } public synchronized void Larga() { ncab++; notify(); } }
public class Cesto { private int ncesto; public Cesto ( int n ) { ncesto = n; } public synchronized void Pega() { try { while ( ncesto == 0 ) wait(); ncesto--; } catch (Exception e ){} } public synchronized void Larga() { ncesto++; notify(); } }
public class Nadador extends Thread { String nome; Cesto cesto; Cabine cabine; int n; public Nadador ( int n, Cesto cesto, Cabine cabine ) { this.n = n; this.cesto = cesto; this.cabine = cabine; } public void run() { try { cesto.Pega(); cabine.Pega(); System.out.println("..... "+ n +“ RETIRANDO A ROUPA"); sleep ( (int) ( Math.random() * 5000 )); cabine.Larga(); System.out.println(“..."+ n +“ NADANDO "); sleep ( (int) ( Math.random() * 5000 )); cabine.Pega(); System.out.println("....."+ n +" COLOCANDO A ROUPA"); sleep ( (int) ( Math.random() * 5000 )); cabine.Larga(); cesto.Larga(); } catch ( Exception e ) {} } }
public class Main { public static void main ( String args[]) { Cabine cab; Cesto cesto; Nadador nadador[]; cab = new Cabine( 4 ); cesto = new Cesto ( 7 ); nadador = new Nadador[ 20 ]; for ( int i = 0; i <= 19; i++ ) { nadador[i]= new Nadador(i,cesto,cab); nadador[i].start(); } } }
IMPLEMENTAÇÃO DE ARQUIVOS DESCRITORDE ARQUIVO: É UMA ESTRUTURA ( UM REGISTRO ) QUE CONTÉM TODAS AS INFORMAÇÕES SOBRE O ARQUIVO.
DESCRITOR DE UM ARQUIVO: ATRIBUTOS + LOCALIZAÇÃO DO ARQUIVO EM DISCO
MEMORIA OPEN ARQ / DESCR CLOSE UNIX / LINUX O DESCR. ARQ >>>>>INODE
TDAA OS SISTEMAS DE ARQUIVOS, NORMALMENTE, MANTÉM, NA MEMÓRIA, UMA TABELA DE REGISTROS DESCRITORES DE TODOS OS ARQUIVOS ABERTOS.
DESCR. ARQ1 NUM. PROC. UTILIZANDO DESCR. ARQ3 NUM. PROC. UTILIZANDO TDAA DESCR. ARQ 5 NUM. PROC. UTILIZANDO DESCR. ARQ 9 NUM. PROC. UTILIZANDO
ABERTURA DE UM ARQUIVO POR UM PROCESSO: OPEN ( ARQ, RO )
ENTRE TANTAS MARAVILHAS DO UNIX: TODOS OS DISPOSITIVOS DE I /O SÃO TRATADOS COMO ARQUIVOS.
IMPRESSORA VIDEO TECLADO TODOS SÃO CONSIDERADOS E TRATADOS COMO ARQUIVOS
A ENTRADA 0 É O ARQUIVO DE ENTRADA PADRÃO, RO TECLADO A ENTRADA 1 É O ARQUIVO DE SAÍDA PADRÃO, W VÍDEO
READ ( X, Y, Z ) ; READ ( 0, X, Y, Z ) ; WRITE ( A, B, C ) ; WRITE ( 1, A, B, C ) ;
UM DIRETÓRIO DE UMA PARTIÇÃO LINUX NOME DO ARQUIVO 1 NUM. DO INODE NOME DO ARQUIVO 2 NUM. DO INODE NOME DO ARQUIVO 3 NUM. DO INODE NOME DO ARQUIVO ... NUM. DO INODE NOME DO ARQUIVO N NUM. DO INODE
REGISTRO DESCRITOR DE ARQUIVO INODE 10 BLOCOS DE 4 KBYTES CADA DONO DADOS DATA DADOS PERMISSÃO ........... ETC ... DADOS 0 1 DADOS DADOS ........... 9 DADOS 10 BLOCO COM 1024 APONTADORES 1024 BLOCOS COM 4 KB 12
DOS E WINDOWS NOME DATA, DONO, ... ........................ 9 0 8 1 7 2 EOF 3 RUIM EOF 4 0 5 LIVRE 6 4 7 2 8 9 1
IMPLEMENTAÇÃO DE ARQUIVOS EM JAVA DESCRITOR DE ARQUIVO: É UM OBJETO QUE CONTÉM TODAS AS INFORMAÇÕES SOBRE O ARQUIVO.
JAVA ENXERGA UM ARQUIVO COMO SENDO UM FLUXO SEQUENCIAL DE BYTES. UM STREAM DE BYTES. UM DESCRITOR DE ARQUIVO EM JAVA PASSA A SER UM OBJETO DE FLUXO. TRES OBJETOS DE FLUXOS SÃO CRIADOS AUTOMATICAMENTE QUANDO SE INICIA A EXECUÇÃO DE UM PROGRAM EM JAVA: System.in System.out System.err
BYTES STREAM • CHARACTER STREAM (UNICODE 16 BITS)
CLASSES ABSTRATAS PARA BYTES STREAM: InputStream OutputStream
CLASSES ABSTRATAS PARA CHARACTER STREAM: READERWRITER
FONTE ARQUIVO MEMÓRIA REDE TECLADO ETC . . . STREAM CHARACTERS UNICODE 16 BITS BufferReader CharArrayReader InputStreamReader FilterReader PipedReader StringReader Super Classe Reader PROGRAMA
DESTINO ARQUIVO MEMÓRIA REDE VÍDEO ETC . . . STREAM CHARACTERS UNICODE 16 BITS BufferWriter CharArrayWriter FilterWriter PipedWriter Super Classe Writer PROGRAMA
FONTE ARQUIVO MEMÓRIA REDE TECLADO ETC . . . STREAM BYTES 8 BITS BufferedInputStream DataInputStream FilterInputStream ObjectInputStream PipedInputStream StringBufferInputStream Super Classe InputStream PROGRAMA
DESTINO ARQUIVO MEMÓRIA REDE VÍDEO ETC . . . STREAM BYTES 8 BITS BufferOutputStream DataOutputStream FilterOutputStreamPipedOutputStream Super Classe OutputStream PROGRAMA
import java.io.*; public class Main{ public static void main(String[] args){ echo ( System.in ); } public static void echo(InputStream instream){ int i; try { while (true) { i = instream.read(); if ( i == -1 ) break; // observe que sem o “cast” um caracter "A", por exemplo, // seria escrito como "65" char c = (char) i; System.out.print( c ); } } catch (IOException e) { System.err.println(e); } } }
import java.io.*; class FileOutputDemo{ public static void main (String args[] ){ FileOutputStream out; PrintStream p; try{ // Cria um novo file output stream // conecta ao arquivo chamado "arq.txt" out = new FileOutputStream ( "arq.txt"); // conecta o print stream ao output stream p = new PrintStream ( out ); for ( int i = 0; i <= 20; i++ ) p.println (" jdfgfdgdfhlkjasdhflksdfds "+i); p.close(); } catch (Exception e ) { System.err.println( e ); } } }
Filtros Streams As classes java.io.FilterInputStream e java.io.FilterOutputStream são subclasses concretas de InputStream e OutputStream que de algum modo modificam dados lidos (escritos) de um stream básico. Raramente essas classes são diretamente utilizadas. Porém, suas subclasses são extremamente importantes, especialmente as classes DataInputStream e DataOutputStream. Um filtro stream é conectado a um stream básico quando o stream original é passado ao construtor do stream filtro.
Por exemplo: Para criar um novo DataOutputStream de um FileOutputStream pode se fazer: FileOutputStream fos = new FileOutputStream( "arq.txt" ); DataOutputStream dos = new DataOutputStream( fos ); É muito comum em Java a prática de se combinar filtros na forma: DataOutputStream dos = new DataOutputStream ( new FileOutputStream( " arq.txt" ) );
import java.io.*; class FileInputDemo{ public static void main (String args[] ){ FileInputStream arq; DataInputStream in; try{ // Abre um arquivo existente chamado "arq.txt“ arq = new FileInputStream ( "arq.txt"); // CONVERTE o arquivo inputstream em um // datainputstream in = new DataInputStream ( arq ); while ( in.available() != 0 ) System.out.println( in.readLine() ); in.close(); } catch (IOException e ) { System.err.println( e); } } }
PIPES Os pipes são canais de comunicação sincronizados entre threads. Um pipe é estabelecido entre dois threads: um thread envia dados para outro gravando em um PipedOutputStream (uma subclasse de Outputstream). O thread destino lê as informações do pipe via um PipedInputStream (uma subclasse de InputStream). Vejam os exemplos:
import java.io.*; public class ThrFonte extends Thread { Writer pipe; String linha; public ThrFonte ( Writer p ){ pipe = p; } public void run() { try{ BufferedWriter out = new BufferedWriter ( pipe ); DataInputStream teclado = new DataInputStream ( System.in ); for ( int i = 0; i < 10; i++ ){ linha = teclado.readLine(); out.write( linha ); out.newLine(); } out.flush(); out.close(); } catch ( IOException erro ) { System.err.println( erro ); } } }