Skip to content

Executor

An Executor is an object that executes submitted Runnable tasks.

What is ExecutorService?

The Java ExecutorService is a construct that allows you to pass a task to be executed by a thread asynchronously. This service creates and maintains a reusable pool of threads for executing submitted tasks.

The service also manages a queue, which is used when there are more tasks than the number of threads in the pool and there is a need to queue up tasks until there is a free thread available to execute the task.

ThreadPoolExecutor

In this piece we want to look at ThreadPoolExecutor implementation of the ExecutorService with regards to Android Development.

To instantiate a ThreadpoolExecutor, You can either directly instantiate it using one of its constructor overloads, for example;

ExecutorService executorService = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

In the above we've instantiated 10 threads with a KeepAlive parameter of 0 milliseconds.

You can also instantiate it using one of the factory methods in the Executors class.

ExecutorService executor = Executors.newFixedThreadPool(10);

The above code has instantiated a ThreadPoolExecutor of 10 threads.

To instantiate a ThreadPoolExecutor of only one thread use the newSingleThreadExecutor() method:

ExecutorService executor = Executors.newSingleThreadExecutor()

To instantiate a ThreadPoolExecutor that adds threads as needed use the newCachedThreadPool() method:

ExecutorService executor = Executors.newCachedThreadPool();

When you instantiate your Executor Service, a few parameters are initialized. Depending on how you instantiated your Executor Service, you may manually specify these parameters or they may be provided for you by default. These parameters are:

  • corePool size - minimum number of threads that should be kept in the pool.

  • maxPool size - the maximum number of workers that can be in the pool.

  • workQueue - used to queue up tasks for the available worker threads.

  • keepAliveTime - If the current number of worker threads exceeds the core pool size and a keepAliveTime is set, then worker threads are shut down when there is no more work to do until the number of worker threads is back to the core pool size; a thread will wait for work for the keepAlive time, and when that is exceeded and no work arrives, it will shut down.

  • threadFactory

  • rejectedExecutionHandler

Quick Executor Examples

Let's start by looking at some snippets of code before writing full examples later in the article, in both Java and Kotlin:

1. Using Executor with Handler

public DownloadStatusDeliveryImpl(final Handler handler) {
    this.mDownloadStatusPoster = new Executor() {
        public void execute(Runnable command) {
            handler.post(command);
        }
    };
}

2. Example 2

package executortest;

import java.time.LocalDate;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Client {

    public static void main(String[] args) {

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.gc();
            }
        }, 10000, 30000);

        ExecutorService executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>(), new RejectedExecutionHandler() {

                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        System.out.println("Runnable rejected :: " + LocalDate.now());
                    }
                });

        while (true) {

            for (int i = 0; i < 10; i++) {
                executorService.execute(new Runnable() {

                    public void run() {

                        System.out.println("Thread executed");
                    }
                });
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

3. Example 3

package executorsexample;

/**
 *
 * @author jessi
 */
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ExecutorsExample {

    public static void main(String[] args) {
        System.out.println("Inside : " + Thread.currentThread().getName());

        System.out.println("Creating Executor Service with a thread pool of Size 4");
        ExecutorService executorService = Executors.newFixedThreadPool(4);

        Runnable task1 = () -> {
            System.out.println("Executing Task1 inside : " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException ex) {
                throw new IllegalStateException(ex);
            }
        };

        Runnable task2 = () -> {
            System.out.println("Executing Task2 inside : " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException ex) {
                throw new IllegalStateException(ex);
            }
        };

        Runnable task3 = () -> {
            System.out.println("Executing Task3 inside : " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException ex) {
                throw new IllegalStateException(ex);
            }
        };

        Runnable task4 = () -> {
            System.out.println("Executing Task4 inside : " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException ex) {
                throw new IllegalStateException(ex);
            }
        };

        Runnable task5 = () -> {
            System.out.println("Executing Task5 inside : " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException ex) {
                throw new IllegalStateException(ex);
            }
        };

        Runnable task6 = () -> {
            System.out.println("Executing Task6 inside : " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException ex) {
                throw new IllegalStateException(ex);
            }
        };

        System.out.println("Submitting the tasks for execution...");
        executorService.submit(task1);
        executorService.submit(task2);
        executorService.submit(task3);
        executorService.submit(task4);
        executorService.submit(task5);
        executorService.submit(task6);

        executorService.shutdown();
    }
}

Let's look at some full examples in Android.

Example 1: Android ThreadPoolExecutor simple Example

Here is a simple step by step example to teach you the threadpoolexecutor in android.

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No third party dependencies are needed for this example.

Step 3: Design Layout

Design a simple layout with buttons and textviews:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.example.bajian.androidthreadpooldemo.MainActivity"
    tools:showIn="@layout/activity_main">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="newCachedThreadPool"
        android:onClick="newCachedThreadPool"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="newFixedThreadPool"
        android:onClick="newFixedThreadPool"/>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="newScheduledThreadPool"
        android:onClick="newScheduledThreadPool"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="stop"
        android:onClick="stop"/>

</LinearLayout>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="newSingleThreadExecutor"
        android:onClick="newSingleThreadExecutor"/>

</LinearLayout>

Step 5: Write Code

Go to MainActivity.java and start by adding imports, among them the following:

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

In our MainActivity define two instance fields:

public class MainActivity extends AppCompatActivity {

    private Runnable r;
    private ScheduledExecutorService scheduledThreadPool;

The method below shows you how to create a Create a cacheable & infinite thread pool. If the length of the thread pool exceeds the processing needs, idle threads can be recycled flexibly. If there is no recycling, new threads can be created. The sample code is as follows:

    public void newCachedThreadPool(View v){
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e . printStackTrace ();
            }
            cachedThreadPool.execute(new Runnable() {

                @Override
                public  void  run () {
                    System.out.println(index);
                    System.out.println(Thread.currentThread().getName());
                    try {
                        Thread.sleep(index * 1000);
                    } catch (InterruptedException e) {
                        e . printStackTrace ();
                    }
                }
            });
        }
    }

The method below shows you how to create a fixed-length thread pool, which can control the maximum concurrent number of threads, and the excess threads will wait in the queue. The size of the fixed-length thread pool is best set according to system resources. Such as Runtime.getRuntime().availableProcessors()

    public void newFixedThreadPool(View v){
        int num=Runtime.getRuntime().availableProcessors();
        System.out.println("Runtime.getRuntime().availableProcessors()->"+num);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                @Override
                public  void  run () {
                    try {
                        System.out.println(index);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e . printStackTrace ();
                    }
                }
            });
        }
    }

Here is how we will shut down our ThreadPools:

    public void stop(View v){
        if (scheduledThreadPool!=null)
            scheduledThreadPool.shutdownNow();
        //        scheduledThreadPool.shutdown();
//        scheduledThreadPool.shutdownNow();
    }

The method below shows you how to create a single-threaded thread pool, it will only use a unique worker thread to perform tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority). Single thread in Android can be used for database operations, file operations, application batch installation, application batch deletion, etc., which are not suitable for combined transmission but may be IO blocking and affect the UI thread response.

    public void newSingleThreadExecutor(View v){

        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            singleThreadExecutor.execute(new Runnable() {

                @Override
                public  void  run () {
                    try {
                        System.out.println(index);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e . printStackTrace ();
                    }
                }
            });
        }
    }

Here is the full code:

MainActivity.java

package com.example.bajian.androidthreadpooldemo;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

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

public class MainActivity extends AppCompatActivity {

    private Runnable r;
    private ScheduledExecutorService scheduledThreadPool;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super . onCreate (savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

    }

    public void newCachedThreadPool(View v){
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;

            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e . printStackTrace ();
            }
            cachedThreadPool.execute(new Runnable() {

                @Override
                public  void  run () {
                    System.out.println(index);
                    System.out.println(Thread.currentThread().getName());
                    try {
                        Thread.sleep(index * 1000);
                    } catch (InterruptedException e) {
                        e . printStackTrace ();
                    }
                }
            });
        }
    }

    public void newFixedThreadPool(View v){
        int num=Runtime.getRuntime().availableProcessors();
        System.out.println("Runtime.getRuntime().availableProcessors()->"+num);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                @Override
                public  void  run () {
                    try {
                        System.out.println(index);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e . printStackTrace ();
                    }
                }
            });
        }
    }

    public void stop(View v){
        if (scheduledThreadPool!=null)
            scheduledThreadPool.shutdownNow();
        //        scheduledThreadPool.shutdown();
//        scheduledThreadPool.shutdownNow();
    }
    /**
     * The choice between Timer and ScheduledExecutorService
     * Create a fixed-length thread pool to support timing and periodic task execution.
     * In fact, when the time to execute the task is greater than the interval we specify, it will not open up a new thread to execute the task concurrently at the specified interval. But wait for the thread to finish executing
     *   @param v
     */
    public void newScheduledThreadPool(View v){

        scheduledThreadPool = Executors.newScheduledThreadPool(5);

        // Execution delayed by 3 seconds.
/*
        scheduledThreadPool.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("delay 3 seconds");
            }
        }, 3, TimeUnit.SECONDS);
*/

        r=new Runnable() {

            @Override
            public  void  run () {
                try {
                    Thread . Sleep( 5000 ); // In fact, when the time to execute the task is greater than the interval we specify, it will not open up a new thread to execute the task concurrently at the specified interval. But wait for the thread to finish executing
                } catch (InterruptedException mE) {
                    mE.printStackTrace();
                }
                System.out.println("delay 1 seconds, and excute every 3 seconds");
            }
        };
//         Indicates that it will be executed every 3 seconds after a delay of 1 second.
//         ScheduledExecutorService is safer and more powerful than Timer. There will be a demo for comparison later.
//         When executing a task, if the specified scheduled execution time scheduledExecutionTime<= systemCurrentTime, the task will first be executed once; then according to the execution time, the current system time and the period parameters, the number of expired executions is calculated, and the calculation is based on: (systemCurrentTime -scheduledExecutionTime)/period, the number of times that the calculation is executed again; finally, the execution is fixed and repeated according to the period parameter
        scheduledThreadPool.scheduleAtFixedRate(r, 1, 3, TimeUnit.SECONDS);
/*        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("excute every 2 seconds");
            }
        }, 1, 2, TimeUnit.SECONDS);*/

    }

    public void newSingleThreadExecutor(View v){

        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            singleThreadExecutor.execute(new Runnable() {

                @Override
                public  void  run () {
                    try {
                        System.out.println(index);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e . printStackTrace ();
                    }
                }
            });
        }
    }

    @Override
    public  boolean  onCreateOptionsMenu ( Menu  menu ) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        // noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author

Example 2 - Android ThreadPoolExecutor

This is a simple example written in Java.

Step 1: Dependencies

No external dependencies are needed.

Step 2: Create MainActivity

Create your MainActivity as follows:

MainActivity.java

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    /**
   * Gets the number of available cores
   * (not always the same as the maximum number of cores)
   **/
    private static int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
    // Sets the amount of time an idle thread waits before terminating
    private static final int KEEP_ALIVE_TIME = 1000;

    // Sets the Time Unit to Milliseconds
    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.MILLISECONDS;

    // Used to update UI with work progress
    private int count = 0;

    // This is the runnable task that we will run 100 times
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // Do some work that takes 50 milliseconds
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // Update the UI with progress
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    count++;
                    String msg = count < 100 ? "working " : "done ";
                    updateStatus(msg + count);
                }
            });

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    // button click - performs work on a single thread
    public void buttonClickSingleThread(View view) {
        count = 0;
        Executor mSingleThreadExecutor = Executors.newSingleThreadExecutor();

        for (int i = 0; i < 100; i++) {
            mSingleThreadExecutor.execute(runnable);
        }
    }

    // button click - performs work using a thread pool
    public void buttonClickThreadPool(View view) {
        count = 0;
        ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(
                NUMBER_OF_CORES + 5,   // Initial pool size
                NUMBER_OF_CORES + 8,   // Max pool size
                KEEP_ALIVE_TIME,       // Time idle thread waits before terminating
                KEEP_ALIVE_TIME_UNIT,  // Sets the Time Unit for KEEP_ALIVE_TIME
                new LinkedBlockingDeque<Runnable>());  // Work Queue

        for (int i = 0; i < 100; i++) {
            mThreadPoolExecutor.execute(runnable);
        }
    }

    private void updateStatus(String msg) {
        ((TextView) findViewById(R.id.text)).setText(msg);
    }

}

Step 4: Create Layout

Here is our MainActivity layout:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_padding="20dp"
    android_orientation="vertical"
    tools_context=".MainActivity">

    <LinearLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_padding="5dp"
        android_orientation="vertical">

        <TextView
            android_id="@+id/text"
            android_gravity="center"
            android_layout_width="match_parent"
            android_layout_margin="10dp"
            android_layout_height="wrap_content"
            android_text="@string/app_name" />

        <Button
            android_id="@+id/singleButton"
            android_layout_width="match_parent"
            android_layout_height="wrap_content"
            android_onClick="buttonClickSingleThread"
            android_text="Single Thread" />

        <Button
            android_id="@+id/poolButton"
            android_layout_width="match_parent"
            android_layout_height="wrap_content"
            android_onClick="buttonClickThreadPool"
            android_text="Thread Pool" />

    </LinearLayout>

</ScrollView>

Reference

Download.

Example 3: Kotlin Android ThreadPoolExecutor Example

Let;s look at a ThreadPoolExecutor example in a step by step manner.

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No third party dependencies are needed.

Step 3: Create layout

We need to create a single layout and add some progressbars to it:

activity_executor.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.kotlin.siddhant.androidexecutorexample.ExecutorActivity">

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="331dp"
        android:layout_height="44dp"
        android:layout_marginEnd="26dp"
        android:layout_marginStart="27dp"
        android:layout_marginTop="26dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:id="@+id/progressBar2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="331dp"
        android:layout_height="44dp"
        android:layout_marginEnd="26dp"
        android:layout_marginStart="27dp"
        android:layout_marginTop="23dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar" />

    <ProgressBar
        android:id="@+id/progressBar3"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="331dp"
        android:layout_height="44dp"
        android:layout_marginEnd="26dp"
        android:layout_marginStart="27dp"
        android:layout_marginTop="25dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar2" />

    <ProgressBar
        android:id="@+id/progressBar4"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="331dp"
        android:layout_height="44dp"
        android:layout_marginEnd="26dp"
        android:layout_marginStart="27dp"
        android:layout_marginTop="27dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar3" />

    <ProgressBar
        android:id="@+id/progressBar5"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="331dp"
        android:layout_height="44dp"
        android:layout_marginEnd="26dp"
        android:layout_marginStart="27dp"
        android:layout_marginTop="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar4" />

    <Button
        android:id="@+id/btnStart"
        android:layout_width="332dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="25dp"
        android:layout_marginStart="27dp"
        android:layout_marginTop="40dp"
        android:text="Start"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar5" />
</android.support.constraint.ConstraintLayout>

Step 4: Write Code

We use the MVP Design Pattern. Start by creating a Contract:

Contract.kt

public class Contract
{
    public interface View
    {
        public fun initView()
    }

    public interface Presenter
    {
        public fun onClick()
    }

}

Then extend the Thread class to create our CounterThread:

CounterThread.kt

import android.app.Activity
import android.widget.ProgressBar

public class CounterThread(progressBar: ProgressBar,activity:Activity):Thread()
{
    var progressBar=progressBar
    var activity=activity

    override fun run() {
        super.run()
        for (progress in 0..100 step 10) // step is use to increase count by 10 (it shows jump)
        {

            (activity as ExecutorActivity).runOnUiThread {
               progressBar.setProgress(progress) // here we set progress android
             }
            Thread.sleep(1000)
        }

    }
}

Then create our ExecutorPresentor:

ExecutorPresenter.kt

import android.app.Activity
import java.util.concurrent.Executor
import java.util.concurrent.Executors

/**
 * Created by Siddhant on 22/03/18.
 */
public class ExecutorPresentor(activity:Activity):Contract.Presenter
{
    var activity=activity as ExecutorActivity
    init {
        (activity as ExecutorActivity)?.initView()
    }
    override fun onClick()
    {
        activity?.initView()
        var executor=Executors.newScheduledThreadPool(2)
        var counterThread=CounterThread(activity.progressBar!!,activity)
        var counterThread2=CounterThread(activity.progressBar2!!,activity)
        var counterThread3=CounterThread(activity.progressBar3!!,activity)
        var counterThread4=CounterThread(activity.progressBar4!!,activity)
        var counterThread5=CounterThread(activity.progressBar5!!,activity)

        executor.execute(counterThread)
        executor.execute(counterThread2)
        executor.execute(counterThread3)
        executor.execute(counterThread4)
        executor.execute(counterThread5)
    }

}

The finally the ExecutorActivity which is the launcher activity:

ExecutorActivity.kt

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.ProgressBar
import kotlinx.android.synthetic.main.activity_executor.*

class ExecutorActivity : AppCompatActivity(),Contract.View, View.OnClickListener {

    var progressBar:ProgressBar?=null
    var progressBar2:ProgressBar?=null
    var progressBar3:ProgressBar?=null
    var progressBar4:ProgressBar?=null
    var progressBar5:ProgressBar?=null
    var btnStart:Button?=null

    var presenter:ExecutorPresentor?=null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_executor)
        presenter= ExecutorPresentor(this)
    }
    // Progressbar initialization
    override fun initView() {
        progressBar=findViewById(R.id.progressBar)
        progressBar2=findViewById(R.id.progressBar2)
        progressBar3=findViewById(R.id.progressBar3)
        progressBar4=findViewById(R.id.progressBar4)
        progressBar5=findViewById(R.id.progressBar5)
        btnStart=findViewById(R.id.btnStart)
        btnStart?.setOnClickListener(this)
    }

    //on click of btnStart to perform action on click
    override fun onClick(view: View?)
    {
        when(view?.id)
        {
            R.id.btnStart ->
                presenter?.onClick()

        }
    }

}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author