Java/Thread

Cada objeto gerado pela classe java.lang.Thread cria uma thread. Também conhecida em línguas lusófonas como linha de execução.

Cada uma dessas linhas de execução podem ser executadas em paralelo, possibilitando à aplicação a execução de instruções relativamente simultâneas.

A thread mainEditar

Toda aplicação tem ao menos uma thread, não-daemon, em tempo de execução: a thread main.

A thread main, criada automaticamente pela JVM quando uma aplicação é iniciada, é responsável por executar o código inicial da aplicação (comumente inserido no corpo do método public static void main(String... args)).

public static void main(String... args) {
    Thread t = Thread.currentThread();
    String nome = t.getName();
    long id = t.getId();
    System.out.println("Nome: " + nome + ", id: " + id);
}
Nome: main, id: 1

Thread Thread.currentThread() devolve uma referência do objeto Thread correspondente à thread que executa a chamada desse método. No código acima, foi devolvida uma referência à thread main.

String getName() foi utilizado para obter o nome da thread, complementarmente há o método void setName(String) que altera o nome da thread.

long getId() devolve um long automaticamente atribuído quando a thread é criada. Esse valor é único e não é reutilizado quando a thread morre.

Criando threadsEditar

Para criar sua própria thread por meio da classe Thread, é preciso realizar 3 etapas:

  1. Definir o código a ser executado pela thread;
  2. Referenciar esse código em uma instância de Thread e;
  3. Chamar o método void start() dessa classe.

Definindo o códigoEditar

O código que será executado por uma thread deve ser definido no método void run() da interface java.lang.Runnable.

class Executavel implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread());	
    }
}

Já que Runnable é uma interface funcional, é possível reescrever o código acima da seguinte forma.

Runnable runnable = () -> System.out.println(Thread.currentThread());

Uma vez que a classe Thread implementa Runnable, alternativamente é possível estender Thread e inserir o código em uma sobrescrita do método void run().

class LinhaDeExecucao extends Thread {

    @Override
    public void run() {
        System.out.println(Thread.currentThread());	
    }
}

Instanciando a classe ThreadEditar

Por meio de referência a Runnable.

class EstudandoThreads  {

    public static void main(String[] args) {
        Runnable runnable = () -> System.out.println(Thread.currentThread());
        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable, "Thread com Runnable");
    }
}

Por meio de instância de subclasse de Thread.

class EstudandoThreads  {

    public static void main(String[] args) {
        LinhaDeExecucao thread1 = new LinhaDeExecucao("subclasse de Thread");
        LinhaDeExecucao thread2 = new LinhaDeExecucao();
    }
}

class LinhaDeExecucao extends Thread {

    public LinhaDeExecucao() {}

    public LinhaDeExecucao(String nome) {
        super(nome);
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread());	
    }
}

O parâmetro String name, encontrado nos construtores Thread(String name) e Thread(Runnable target, String name) especifica um nome para a thread. Caso não especificado no construtor o nome da thread será criado automaticamente derivado do modelo Thread-0, onde 0 é um número incrementado a cada nova thread criada sem definição de nome.

Executando a threadEditar

class EstudandoThreads  {

    public static void main(String[] args) {
        Runnable runnable = () -> System.out.println(Thread.currentThread());
        Thread thread = new Thread(runnable);
        thread.start();
    }
}
Thread[Thread-0,5,main]

Na linha 6 o método sobrescrito String toString() é chamado implicitamente por System.out.println(Object). String toString() da classe Thread define o modelo Thread[NOME, PRIORIDADE, GRUPO] como pode ser observado na saída da execução do código. PRIORIDADE e GRUPO serão abordados em seções posteriores.

Na linha 8 a thread Thread-0 é iniciada.

Evite ThreadGroupEditar

java.lang.ThreadGroup group inclui a thread em um grupo de threads. A utilização de ThreadGroup deve ser evitada[1].

Então evite os seguintes construtores da classe Thread.

Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, String name)

Bem como os métodos abaixo.

static int enumerate(Thread[] tarray)
static int activeCount()
final ThreadGroup getThreadGroup()

Métodos estáticosEditar

dumpStack()
getAllStackTraces()
getDefaultUncaughtExceptionHandler()
holdsLock(Object obj)
interrupted()
setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
sleep(long millis)
sleep(long millis, int nanos)
yield()

Métodos de instânciaEditar

checkAccess()
countStackFrames()
getContextClassLoader()
getPriority()
getState()
getThreadGroup()
getUncaughtExceptionHandler()
interrupt()
isAlive()
isDaemon()
isInterrupted()
join()
join(long millis)
join(long millis, int nanos)
setContextClassLoader(ClassLoader cl)
setDaemon(boolean on)
setPriority(int newPriority)
setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
  1. Item 73 - JOSHUA, Bloch. Effective Java. 2.ª edição, 2009.