O que são Threads? O que é MultiThreading?
É comum que programas realizem várias tarefas, mas em certos casos, é necessário ou útil que tais tarefas possam ser executadas "simultaneamente", isto é, que duas ou mais partes de um mesmo programa, digamos suas sub-tarefas,) esteja ativas, sendo executadas ao mesmo tempo. Na verdade, o sistema operacional deve controlar a execução destas partes, dividindo o tempo do(s) processador(es) do sistema entre tais sub-tarefas, da forma mais transparente possível para o usuário e para o programador.
Uma thread é como uma sub-tarefa de um programa, ou mais tecnicamente falando, uma linha de execução do programa. Enquanto um programa é usualmente tratado como um processo pelo sistema operacional, possuindo um espaço de endereçamento e recebendo sua quota de tempo de processamento do sistema, as threads de um processo compartilham seu espaço de endereçamento enquanto recebem, cada uma, sua quota de tempo de processamento, passando a impressão de que várias partes do programa estão em execução simultânea.
Um programa é multithreaded quando possui várias threads que o auxiliam a executar suas tarefas.
Existem inúmeras aplicações para programas multithreaded, tais como a construção de servidores capazes de atender "simultaneamente" com suas várias threads diferentes clientes (processos externos). Outra possibilidade de uso é a construção de interfaces capazes de responder mais prontamente, por exemplo, botões que permitam pausar ou cancelar operações durante sua operação.
O Java oferece recursos que facilitam a criação de programas multithreaded. A classe java.lang.Thread representa uma abstração de uma thread assim como a interface java.lang.Runnable que representa a especificação a ser seguinda por classes que pretendam ser tratadas como threads (veja JavaFaq 0064 para um discussão sobre interfaces).
Para criarmos uma thread geralmente definimos uma subclasse da java.lang.Thread onde implementamos o método run() tal como abaixo:
public class Contador extends Thread { // variáveis da class (opcionais) private String id; // identificador private int inicio; // valor de início da contagem private int fim; // valor de término da contagem private int incremento; // valor do incremento da contagem // construtor (opcional) public Contador(String s, int i, int f, int inc) { id = s; inicio = i; fim = f; incremento = inc; } // código da thread public void run() { for(int c = inicio; c<=fim; c+=incremento) System.out.println(id+":"+c); } }
O método run() corresponde ao trecho de código associado a thread que se pretende construir. O código contido neste método tem sua execução controlado pelos métodos:
Estes métodos (e outros disponíveis na classe java.lang.Thread) permitem controlar uma ou mais threads definidas por um programa.
A seguir um pequeno exemplo que usa a classe Contador dada acima:
public class ThreadDemo { public static void main(String args[]) { Contador c1 = new Contador("Contador 1", 0, 5, 1); Contador c2 = new Contador("Contador 2", 10, 40, 5); Contador c3 = new Contador("Contador 3", 100, 600, 100); c1.start(); c2.start(); c3.start(); } }
No exemplo criamos três contadores com valores distintos de início, fim e incremento. Embora sejam iniciados sequencialmente note que suas saídas (identificadas pelas strings dadas) ocorrem "embaralhadas" indicando que os três contadores estão em execução "simultânea". Um possível resultado pode ser visto abaixo.
>java ThreadDemo Contador 1:0 Contador 2:10 Contador 2:15 Contador 3:100 Contador 1:1 Contador 1:2 Contador 2:20 Contador 1:3 Contador 1:4 Contador 3:200 Contador 3:300 Contador 2:25 Contador 2:30 Contador 2:35 Contador 2:40 Contador 1:5 Contador 3:400 Contador 3:500 Contador 3:600