Concurrency-Chapter2-Executer & Callable & Scheduled Executer Service

Hasan Kadir Demircan
3 min readMay 13, 2022

Executer

We can directly create and manage threads in the application by creating Thread objects. However, if we want to abstract away the low-level details of multi-threaded programming, we can make use of the Executer Interface.

Executor is an interface that declares only one method: void execute(Runnable). This may not look like a significant interface by itself but its derived classes (or interfaces), such as ExecutorService, ThreadPoolExecutor, and ForkJoinPool, support useful functionality.

İt is recommended that you use this framework anytime you need to create and execute a separate task, even if you need only a single thread.

Finally Shutting Down a Thread Executer

ExecuterService service = null;    
try {
service = Executors.newSignleThreadExecutor();
//add tasks to thread executer.
}finally {
if(service !=null) service.shutdown();
}

Let’s look at an example that compares between Runnable and Executor.

Now we can look at another example;

  • Single-thread executor(Executors.newSingleThreadExecutor()), results are guaranteed to be executed in the order in which they are added to the executor service.
  • This is because the main() method is still an independent thread from the ExecutorService, and it can perform tasks while the other thread is running.
  • A thread executor creates a non-daemon thread on the rst task that is executed, so failing to call shutdown() will result in your application never terminating.after shutdown, we can not execute the service. we get an error.
service.shutdown();
service.execute(() -> { System.out.println("java.util.concurrent.RejectedExecutionException" );
});

Output:

  • When we run the application, we will see 2 threads working on that are main and pool-1-thread-1
  • Executors.newSingleThreadExecutor() -> pool-1-thread-1
begin : main
sample runnable
thread execute 1: pool-1-thread-1
end : main
Printing record: 0
Printing record: 1
Printing record: 2
false
thread execute 2: pool-1-thread-1
false
  • If we want to return a result after the thread we need to use Callable. Because Runnable is void and nothing returns.

Callable

The Callable interface was introduced as an alternative to the Runnable interface, since it allows more details to be retrieved easily from the task after it is completed.

Let’s look at an example;

Output:
Runnable!
null
Callable!
1

Another example is;

class
java.util.concurrent.Executors$FinalizableDelegatedExecutorService
30
true
false
true
true

Scheduled Executer Service

The ScheduledExecutorService interface in Java is a sub-interface of ExecutorService interface defined in java.util.concurrent package. This interface is used to run the given tasks periodically or once after a given delay.

  • We created 2 task which are Runnable and Callable.
  • We defined 3 seconds for task1 and 2 seconds for task2.
Output:
task2 message
task1 message!
null
content
  • The scheduleAtFixedRate() is the method of Timer class. It is used to schedule the given task again and again in fixed rate of execution. It will begin after the specified delay.
  • The scheduleWithFixedDelay() method creates a new task after the previous task has finished.
  • For example, if the first task runs at 12:00 and takes five minutes to finish, with a period of 2 minutes, then the second task will start at 12:07.
  • So, if there will be situations where it may take a long time to finish, we should use scheduleWithFixedDelay();

Increasing Concurrency with Pools

  • While a single-thread executor will wait for an available thread to become available before running the next task, a pooled-thread executor can execute the next task concurrently.
  • As long as our number of tasks is less than our number of threads, all tasks will be executed concurrently
  • We can use ScheduledExecutorService instead of ExecutorService, if we want to scheduled.

Github: Concurrency-2

--

--