Resultado diferente em Thread entre Callable e Runnable

Fala ae pessoal. Tudo beleza com vocês?

Resolvi testar se havia alguma diferença entre as classes Callable e o Runnable para executar Threads e aqui para mim o Callable não está funcionando em paralelismo, já o Runnable sim. Poderiam me explicar, e exemplificar o porque disso. Se eu estiver fazendo algo de errado me corrijam, por favor.
Seguem ae as minhas classes.

Classe Principal

package br.com.exemplo.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TesteExceptionThread {

	public static void main(String[] args) {
		try {
			ExemploCallable ec = new ExemploCallable(99);
			ExemploCallable ec2 = new ExemploCallable(11);
		
			ExecutorService thread = Executors.newSingleThreadExecutor();
			ExecutorService thread2 = Executors.newSingleThreadExecutor();
			Integer result = thread.submit(ec).get();
			result = thread2.submit(ec2).get();
			
			System.out.println("\n ");
			
			ExemploRunnable er = new ExemploRunnable(22);
			ExemploRunnable er2 = new ExemploRunnable(11);
			Thread t = new Thread(er);
			Thread t2 = new Thread(er2);
			t.start();
			t2.start();
		}
		catch (NumberFormatException e) {
			e.printStackTrace();
		}
		catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
}

Classe Callable

package br.com.exemplo.thread;

import java.util.concurrent.Callable;

public class ExemploCallable implements Callable<Integer> {

	private Integer numero;
	
	public ExemploCallable(Integer numero) {
		this.numero = numero;
	}
	
	@Override
	public Integer call() throws Exception {
		for(int x = 0; x<=numero; x++) {
			System.out.println(" ===> CALLABLE NUMERO " + numero + " X: " + x + " ");
		}
		return 0;
	}
	
}

Classe Runnable

package br.com.exemplo.thread;

public class ExemploRunnable implements Runnable {

	private Integer numero;
	
	public ExemploRunnable(Integer numero) {
		this.numero = numero;
	}
	
	@Override
	public void run() {
		for(int x = 0; x<=numero; x++) {
			System.out.println(" ===> RUNNABLE NUMERO " + numero + " X: " + x + " ");
		}
	}
	
}

Grande Abraço.

Não é que o “callable não está funcionando em paralelismo”. É você que não entendeu o que é o “callable”.

Fala ae entanglement, tudo bom?

Bom, se não for pedir muito, dá uma explicada ae então, por favor? É porque como o resultado da minha classe principal mostra os dois processos do Callable sequencialmente e os dois do Runnable simultaneamente e impressão que estou tendo é essa.

Abraço.

Vi no seu código uma mania que todo estudante tem, que é a de juntar um comando depois do outro e não entender bem o que está ocorrendo. No seu caso, você usou “submit” e “get”, um encadeado no outro.

A idéia do “callable” é de algo que você vai solicitar para ser executado (sei lá quando), e então você usa o “submit”, mas você precisa de obter o resultado da operação algum tempo depois, com “get”. Mas se você já pedir o get logo de cara, quando você chamar o submit, ele vai ter de esperar até o método call retornar o resultado para o get.

Se você tivesse simplesmente feito algo como:

            ExecutorService thread = Executors.newSingleThreadExecutor();  
            ExecutorService thread2 = Executors.newSingleThreadExecutor();  
            Future<Integer> futureResult = thread.submit(ec);  
            Future<Integer> futureResult2 = thread2.submit(ec2);  
            Integer result = futureResult.get();
            result = futureResult2.get();

teria o comportamento desejado.

Aliás, não se deve usar “newSingleThreadExecutor” a menos que você esteja criando um código que deve ter um comportamento muito previsível e você quer restringir o código a ser executado por uma única thread. Normalmente, usa-se apenas um ExecutorService (não um por Callable ou Runnable), e esse ExecutorService é que cria a quantidade de threads necessárias para rodar seu problema (por exemplo, um Executors.newCachedThreadPool() ou coisa parecida. )

O “get” da interface Future é implementado mais ou menos como se fosse um “Thread.join”. (Não olhei os fontes)

Fala entanglement,
já estava caindo no esquecimento. :oops:

Rapaz não fique chateado com as manias dos estudantes. Hehehe :slight_smile:
Eu coloquei o código assim, um comando seguido do outro, porque o processamento seria muito pouco e rápido e um iria acabar antes que o outro fosse executado e não veria o resultado que eu desejava.
Sobre a correta utilização do Callable, o lugar onde eu tinha lido não tinha explicado tão bem quanto você pô.

Muito Agradecido pela ajuda.

Abraço.