Can I use Callable threads without ExecutorService? Can I use Callable threads without ExecutorService? multithreading multithreading

Can I use Callable threads without ExecutorService?


While interfaces are often created with an intended use case, they are never restricted to be used in that way.

Given a Runnable you can submit it to an ExecutorService, or pass it to the constructor of Thread or you can invoke its run() method directly like you can invoke any interface method without multi-threading involved. And there are more use cases, e.g. AWT EventQueue.invokeLater(Runnable) so never expect the list to be complete.

Given a Callable, you have the same options, so it’s important to emphasize that, unlike your question suggests, invoking call() directly does not involve any multi-threading. It just executes the method like any other ordinary method invocation.

Since there is no constructor Thread(Callable) using a Callable with a Thread without an ExecutorService requires slightly more code:

FutureTask<ResultType> futureTask = new FutureTask<>(callable);Thread t=new Thread(futureTask);t.start();// …ResultType result = futureTask.get(); // will wait for the async completion


The simple direct answer is that you need to use an ExecutorService if you want to use a Callable to create and run a background thread, and certainly if you want to obtain a Future object, or a collection of Futures. Without the Future, you would not be able to easily obtain the result returned from your Callable or easily catch Exceptions generated. Of course you could try to wrap your Callable in a Runnable, and then run that in a Thread, but that would beg the question of why, since by doing so you would lose much.


Edit
You ask in comment,

Do you mean like the code below, which works?

public class Application2 {    public static class WordLengthCallable implements Callable {    public static int count = 0;    private final int numberOfThread = count++;    public Integer call() throws InterruptedException {        int sum = 0;        for (int i = 0; i < 100000; i++) {            sum += i;        }        System.out.println(numberOfThread);        return numberOfThread;    }}    public static void main(String[] args) throws InterruptedException {        new Thread(new MyRunnable()).start();        new Thread(new MyRunnable()).start();        new Thread(new MyRunnable()).start();        new Thread(new MyRunnable()).start();        try {            Thread.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.exit(0);    }    public static class MyRunnable implements Runnable {        @Override        public void run() {            try {                new WordLengthCallable().call();            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}

My reply: Yes. The code in the link "sort of" works. Yes, it creates background threads, but the results from the calculations performed in the Callables are being discarded, and all exceptions are being ignored. This is what I mean by "since by doing so you would lose much".


e.g.,

  ExecutorService execService = Executors.newFixedThreadPool(THREAD_COUNT);  List<Future<Integer>> futures = new ArrayList<>();  for (int i = 0; i < THREAD_COUNT; i++) {     futures.add(execService.submit(new WordLengthCallable()));  }  for (Future<Integer> future : futures) {     try {        System.out.println("Future result: " + future.get());     } catch (ExecutionException e) {        e.printStackTrace();     }  }  Thread.sleep(1000);  System.out.println("done!");  execService.shutdown();

Edit 2
Or if you want the results returned as they occur, use a CompletionService to wrap your ExecutorService, something I've never attempted before:

import java.util.Random;import java.util.concurrent.Callable;import java.util.concurrent.CompletionService;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorCompletionService;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CompletionServiceExample {   public static class WordLengthCallable implements Callable<Integer> {      private Random random = new Random();      public Integer call() throws InterruptedException {         int sleepTime = (2 + random.nextInt(16)) * 500;         Thread.sleep(sleepTime);         return sleepTime;      }   }   private static final int THREAD_COUNT = 4;   public static void main(String[] args) throws InterruptedException {      ExecutorService execService = Executors.newFixedThreadPool(THREAD_COUNT);      CompletionService<Integer> completionService = new ExecutorCompletionService<>(            execService);      for (int i = 0; i < THREAD_COUNT; i++) {         completionService.submit(new WordLengthCallable());      }      execService.shutdown();      try {         while (!execService.isTerminated()) {            int result = completionService.take().get().intValue();            System.out.println("Result is: " + result);         }      } catch (ExecutionException e) {         e.printStackTrace();      }      Thread.sleep(1000);      System.out.println("done!");   }}


import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;public class MainClass {    public static void main(String[] args) {        try {            Callable<String> c = () -> {                System.out.println(Thread.currentThread().getName());                return "true";            };            FutureTask<String> ft = new FutureTask<String>(c);            Thread t = new Thread(ft);            t.start();            String result = ft.get();            System.out.println(result);        } catch (Exception e) {            e.printStackTrace();        }    }}/*   Output:    Thread-0    true */