CodeGym /Cursos /JAVA 25 SELF /Parâmetros e prioridades de threads

Parâmetros e prioridades de threads

JAVA 25 SELF
Nível 51 , Lição 3
Disponível

1. Passagem de parâmetros para threads

Quando você inicia uma thread, muitas vezes quer passar a ela algum “trabalho”: nome de arquivo, intervalo de números ou uma saudação. Uma thread sem parâmetros — é como um entregador sem endereço: corre pela cidade, mas não sabe para onde entregar a pizza.

Como fazer isso?

Em Java, as threads geralmente são criadas de duas formas:

  • Herdando da classe Thread
  • Implementando a interface Runnable (ou usando uma expressão lambda)

A passagem de parâmetros é feita, na maioria das vezes, pelo construtor da classe que implementa Runnable. É simples, seguro e claro. Torne os campos final — e você protegerá os parâmetros contra alterações vindas de outras threads. Usar setters/campos públicos é arriscado por causa de problemas de sincronização.

Exemplo 1: Thread com parâmetro via construtor

Vamos aprimorar um aplicativo didático: processar pedidos de usuários em uma thread separada.

public class OrderProcessor implements Runnable {
    private final String orderId;

    public OrderProcessor(String orderId) {
        this.orderId = orderId;
    }

    @Override
    public void run() {
        System.out.println("Processando pedido: " + orderId + " na thread " + Thread.currentThread().getName());
        // Aqui pode haver um processamento demorado...
    }
}

Criando e iniciando threads:

public class Main {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new OrderProcessor("ORDER-001"));
        Thread thread2 = new Thread(new OrderProcessor("ORDER-002"));
        thread1.start();
        thread2.start();
    }
}

Saída esperada:

Processando pedido: ORDER-001 na thread Thread-0
Processando pedido: ORDER-002 na thread Thread-1

Exemplo 2: Thread com parâmetro via expressão lambda (Java 8+)

Se a tarefa for simples, dá para dispensar uma classe separada.

public class Main {
    public static void main(String[] args) {
        String user1 = "Vasya";
        String user2 = "Katya";

        Thread thread1 = new Thread(() -> {
            System.out.println("Olá, " + user1 + " de " + Thread.currentThread().getName());
        });

        Thread thread2 = new Thread(() -> {
            System.out.println("Olá, " + user2 + " de " + Thread.currentThread().getName());
        });

        thread1.start();
        thread2.start();
    }
}

Por que não usar setters/getters para passar parâmetros?
Se você passa parâmetros por setters ou campos públicos, há o risco de outra thread alterar o valor durante a execução. Isso pode levar a erros difíceis de detectar. É melhor tornar os campos final e passá-los pelo construtor.

2. Prioridades de threads

Em Java, cada thread tem uma prioridade — um número inteiro de 1 a 10, que informa ao escalonador (scheduler) quão “importante” é essa thread em comparação com as outras. Por padrão, todas as threads têm prioridade 5 (Thread.NORM_PRIORITY).

Importante: a prioridade é apenas uma “dica” para o SO. Não é garantia de que uma thread com prioridade 10 rodará mais rápido que uma com prioridade 1. Tudo depende do SO, de suas configurações e da carga atual.

Como definir a prioridade de uma thread?

A classe Thread possui os métodos:

  • setPriority(int newPriority)
  • getPriority()

E três constantes padrão:

  • Thread.MIN_PRIORITY (1)
  • Thread.NORM_PRIORITY (5)
  • Thread.MAX_PRIORITY (10)

Exemplo 3: Definindo a prioridade de uma thread

public class PriorityDemo {
    public static void main(String[] args) {
        Runnable task = () -> {
            System.out.println("Thread " + Thread.currentThread().getName() +
                    " com prioridade " + Thread.currentThread().getPriority());
        };

        Thread low = new Thread(task, "LowPriority");
        Thread norm = new Thread(task, "NormalPriority");
        Thread high = new Thread(task, "HighPriority");

        low.setPriority(Thread.MIN_PRIORITY);    // 1
        norm.setPriority(Thread.NORM_PRIORITY);  // 5
        high.setPriority(Thread.MAX_PRIORITY);   // 10

        low.start();
        norm.start();
        high.start();
    }
}

Saída esperada (a ordem das linhas não é garantida!):

Thread LowPriority com prioridade 1
Thread HighPriority com prioridade 10
Thread NormalPriority com prioridade 5

A prioridade influencia a ordem de execução?

Na maioria dos casos — não. As prioridades podem influenciar quanto tempo de CPU a thread recebe, mas não garantem a ordem de início ou término. Não baseie a lógica do programa em prioridades — use-as como “dicas” suaves, por exemplo, para que uma thread em segundo plano não atrapalhe a principal.

Tabela: Constantes de prioridade de threads

Constante Valor Descrição
Thread.MIN_PRIORITY
1 Prioridade mais baixa
Thread.NORM_PRIORITY
5 Prioridade normal
Thread.MAX_PRIORITY
10 Prioridade mais alta

3. Nomeando threads

O nome da thread é um “apelido” no mundo da multitarefa. Quando você tem dezenas de threads, é mais fácil depurar se, em vez de "Thread-7", você vir "FileUploader-1" no log. Isso é especialmente importante ao analisar logs e buscar erros.

Como definir o nome de uma thread?

O nome pode ser informado diretamente no construtor de Thread ou definido com o método setName. Para obter o nome atual — getName.

Thread t = new Thread(() -> {
    System.out.println("Estou trabalhando!");
}, "MyThreadName");
t.start();

Exemplo 4: Threads nomeadas

public class NamedThreads {
    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            System.out.println("Sou a thread: " + Thread.currentThread().getName());
        }, "Downloader");

        Thread threadB = new Thread(() -> {
            System.out.println("Sou a thread: " + Thread.currentThread().getName());
        });
        threadB.setName("Uploader");

        threadA.start();
        threadB.start();
    }
}

Saída esperada:

Sou a thread: Downloader
Sou a thread: Uploader

4. Prática: várias threads com parâmetros, prioridades e nomes diferentes

Vamos juntar tudo em um único exemplo: cada pedido — uma thread separada com seu próprio nome e prioridade.

public class OrderProcessor implements Runnable {
    private final String orderId;
    private final int processingTimeMs;

    public OrderProcessor(String orderId, int processingTimeMs) {
        this.orderId = orderId;
        this.processingTimeMs = processingTimeMs;
    }

    @Override
    public void run() {
        System.out.println("[" + Thread.currentThread().getName() + "] Iniciei o processamento do pedido " + orderId +
                " (prioridade " + Thread.currentThread().getPriority() + ")");
        try {
            Thread.sleep(processingTimeMs); // simulação de trabalho
        } catch (InterruptedException e) {
            System.out.println("[" + Thread.currentThread().getName() + "] Interrompido!");
        }
        System.out.println("[" + Thread.currentThread().getName() + "] Concluí o processamento do pedido " + orderId);
    }

    public static void main(String[] args) {
        Thread fastOrder = new Thread(new OrderProcessor("FAST-ORDER", 500), "FastOrderThread");
        Thread normalOrder = new Thread(new OrderProcessor("NORMAL-ORDER", 1000), "NormalOrderThread");
        Thread slowOrder = new Thread(new OrderProcessor("SLOW-ORDER", 2000), "SlowOrderThread");

        fastOrder.setPriority(Thread.MAX_PRIORITY);
        normalOrder.setPriority(Thread.NORM_PRIORITY);
        slowOrder.setPriority(Thread.MIN_PRIORITY);

        fastOrder.start();
        normalOrder.start();
        slowOrder.start();
    }
}

O que veremos:

  • Cada thread informa qual pedido está processando, seu nome e sua prioridade.
  • O tempo de processamento é simulado com Thread.sleep.
  • A ordem de conclusão das threads pode não corresponder à prioridade.

5. Pontos importantes e particularidades

Passagem de parâmetros: apenas via construtor!

É mais seguro. Declare os parâmetros como final — eles não poderão ser alterados após a criação do objeto, e nenhuma outra thread vai “injetar” seus próprios valores. Isso é crucial para prevenir condições de corrida.

Prioridades: não baseie nelas a lógica de negócio

Prioridades são como pedir ao garçom: “Pode trazer o café mais rápido?”. Às vezes funciona, às vezes — não. É uma recomendação para o SO, não uma regra de execução.

Nomes de threads: use para depuração

Economiza muito tempo ao analisar logs. Acostume-se a definir nomes significativos desde o início.

6. Erros típicos ao trabalhar com parâmetros e prioridades de threads

Erro nº 1: passar parâmetros por campos públicos. Se você declara os parâmetros como campos comuns e os altera após o início da thread, pode obter resultados imprevisíveis. Use campos final e o construtor.

Erro nº 2: esperar que a prioridade garanta a ordem. Você definiu Thread.MAX_PRIORITY — e acha que a thread será sempre a primeira? Não. Não use prioridades para sincronização ou controle da lógica.

Erro nº 3: threads sem nome nos logs. Quando no log há apenas “Thread-3”, “Thread-7”, é difícil achar o responsável. Dê nomes significativos às threads usando o construtor ou setName.

Erro nº 4: usar o mesmo objeto Runnable para várias threads. Se o objeto Runnable mantém estado e você o passa para várias threads, elas “compartilham” os parâmetros — caminho direto para condições de corrida. Crie um Runnable separado por thread.

Erro nº 5: passar parâmetros por métodos set. Se você define parâmetros por set*-métodos já depois da criação/início da thread, os valores podem mudar “em voo” — a clássica race condition.

1
Tarefa
JAVA 25 SELF, nível 51, lição 3
Bloqueado
Gerenciamento de agentes no marketplace online 🛍️
Gerenciamento de agentes no marketplace online 🛍️
1
Tarefa
JAVA 25 SELF, nível 51, lição 3
Bloqueado
Coordenação de robôs em uma fábrica inteligente 🏭
Coordenação de robôs em uma fábrica inteligente 🏭
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION