VIRICH
VIRICH

Reputation: 177

New thread from Callable instead of Runnable?

Threads are normally created from Runnables. Is there a way to create a thread from a Callable?

public class AddNumImmediately implements Callable {
    private int minRange;
    private int maxRange;
    private Set<Integer> primeNumberList;
    private int step;

    public AddNumImmediately(int minRange, int maxRange, Set<Integer> primeNumberList, int step) {
        this.minRange = minRange;
        this.maxRange = maxRange;
        this.primeNumberList = primeNumberList;
        this.step = step;
    }

    @Override
    public Object call() {
        for (int i = minRange; i <= maxRange; i += step) {
            if (PrimeChecker.isPrimeNumber(i)) {
                primeNumberList.add(i);
            }
        }
        return primeNumberList;
    }
}

And then I try to run my Callable via Thread:

public void setup(int min, int max, int threadNumber) throws InterruptedException {
    Set<Integer> primeNumberList = new LinkedHashSet<>();
    List<Thread> threadList = new ArrayList<>();

    for (int i = 0; i < threadNumber; i++) {
        threadList.add(new Thread(String.valueOf(new AddNumImmediately(min, max, primeNumberList, threadNumber))));
    }
    for (Thread thread : threadList) {
        thread.start();
    }

    for (Thread thread : threadList) {
        thread.join();
    }
    System.out.println(primeNumberList);
}

I know that Callables can be run by an Executor, but is it possible to somehow run them through Thread?

Upvotes: 1

Views: 2344

Answers (4)

Anurag
Anurag

Reputation: 1

You cannot create a new thread from callable. That's there. For a new thread, Thread has to come into picture. Being said that you can use FurtureTask with callable and Thread to get your result back. You can try something like this:

FutureTask<String> f1 = new FutureTask<String>(new Callable<String>() {
    public String call() throws InterruptedException {
        Thread.sleep(1000);
        return "A constant from " + Thread.currentThread().getName();
    }
});

Thread t = new Thread(f1);
t.start();
System.out.println("Calling Get " + Thread.currentThread().getName());
System.out.println(f1.get());
System.out.println("Got Get");

will give you output as :

Calling Get main

A constant from Thread-0

Got Get

Upvotes: 0

maio290
maio290

Reputation: 6742

You're using Callable wrong. A callable returns a <V>, which will become a Future<V> when submitted via an ExecutorService, if you don't work with them, you pick Runnable.

Callable:

A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call.

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

Runnable

The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The class must define a method of no arguments called run.

https://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html

So the proper way with callables would be to return a Set<Integer> and merge these Futures together in your primeNumberList.

Upvotes: 2

Stephen C
Stephen C

Reputation: 718946

Is there a way to create a thread from a Callable?

Short answer: No. The Thread API requires a Runnable not a Callable.

You can work around this with a Runnable wrapper for a Callable, though getting the result from the Callable is a bit messy! A much better idea is to use an ExecutorService. That allows you to avoid the problems of not creating too many threads and (alternatively) managing your own thread pool.

It is work noting that your example doesn't really need a Callable. You are returning a Set that was provided in the AddNumImmediately constructor. The caller could simply keep a reference to that Set object.

Upvotes: 2

Gent Ahmeti
Gent Ahmeti

Reputation: 1599

You can wrap your Callable with a Runnable. Use this helper function to create Thread from Callable.

public static Thread createThreadFromCallable(@NonNull Callable<?> callable) {
    return new Thread(() -> {
        try {
            callable.call();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}

Upvotes: 0

Related Questions