Skip to main content

Command Palette

Search for a command to run...

Threads, Multi-Threading

Published
4 min readView as Markdown
R
Enthusiatic Software Developer with over 4.11 years of experience in building and optimizing Web applications. Proficient in backend development using Java, Spring Boot, Monolithic and Microservices architecture within agile methodologies.

Thread Termination

interrupt(); daemon(true);

//Example using Thread.Interrupt() method to terminate thread.
public class main{
    public static void main(String[] args){
        Thread thread = new Thread(new LongComputationTask(
                                    new BigInteger(200000), new BigInteger(1000000)));
        thread.start();
        thread.interrupt();
    }
    private static class LongComputationTask implements Runnable{
        private BigInteger base;
        private BigInteger power;

        public LongComputationTask(BingInteger base, BigInteger power){
            this.base = base;
            this.power = power;
        }

        @Override
        public void run(){
            System.out.println(base+"^"+power+" = "+ pow(base, power));
        }
        private BigInteger pow(BigInteger base, BigInteger power){
               BigInteger result = BigInteger.ONE;
                for(BigInteger i = BigInteger.ONE; i.compareTo(power)!=0; i.add(BigInteger.ONE)){
                   if(Thread.currentThread().isInterrupted()){
                        System.out.println("Prematurally Interrupted Computation.");
                        return BigInteger.ZERO;
                    }
                    result = result.multiply(base);
                }
              return result;
        }
    }
}

Daemon Thread: Background threads that do not prevent the application from exiting if the main thread terminate as we already know any non daemon thread if it is running even though main thread terminated application doesn't terminate or stop.

Daemon Threads - Scenarios
Scenario 1: Background tasks, that should not block our application from terminating.
Examples: File saving thread in a Text Editor - thread save our files every minutes
Scenario 2: Code in a worker thread is not under our control, and we do not want it to block our application from terminating.

Example: Worker thread that uses an external library

//Daemon Threads to terminate flow
/*
Here we haven't stopped app gracefully becuase we have setDaemon true at very first
*/

//Example using Thread.Interrupt() method to terminate thread.
public class main{
    public static void main(String[] args){
        Thread thread = new Thread(new LongComputationTask(
                                    new BigInteger(200000), new BigInteger(1000000)));
        thread.setDaemon(true);
        thread.start();
        thread.interrupt();
    }
    private static class LongComputationTask implements Runnable{
        private BigInteger base;
        private BigInteger power;

        public LongComputationTask(BingInteger base, BigInteger power){
            this.base = base;
            this.power = power;
        }

        @Override
        public void run(){
            System.out.println(base+"^"+power+" = "+ pow(base, power));
        }
        private BigInteger pow(BigInteger base, BigInteger power){
               BigInteger result = BigInteger.ONE;
                for(BigInteger i = BigInteger.ONE; i.compareTo(power)!=0; i.add(BigInteger.ONE)){
                   if(Thread.currentThread().isInterrupted()){
                        System.out.println("Prematurally Interrupted Computation.");
                        return BigInteger.ZERO;
                    }
                    result = result.multiply(base);
                }
              return result;
        }
    }
}
Summary
Learned how to stop threads by calling the thread.interrupt().
  • If the method does not respond to the interrupt signal by throwing the interruptedException, we need to check for that signal and handle it ourselves.

To prevent a thread from blocking our app from exiting, we set the thread to be a Daemon thread.

Thread coordination

What we learn in this lecture:
1. Threads coordination with Thread.join()
2. Case study

Specifically, we will learn how we can guarantee that a thread upon which we depend completes its work, by the time we expected. This topic is the first step for us to gain full control over other thread's execution, so that in future, we could run certain tasks in parallel and get a significant speed up, but also be able to safely and correctly aggregate the results

Thread Coordination- Why do we need it?
1. Different threads run independently.
2. Order of execution is out of our control.

scenario: 1 Thread B may finish its work before Thread A

Thread coordination - Dependency:
What if one thread depends on another thread?

Naive Solution:
Thread B runs in a loop and keeps checking if Thread A's result is ready. But this will be counterproductive and will slow down thread A

Desired Solution:
Thread B to just go to sleep and completely get out of the way and let thread A finish its work and only when thread A is done Thread B will wake up and take the already fully completed result.

To achieve desired solution we can use following methods:

public final void join();

public final void join(long millis, int nanos);

public final void join(long millis);

public class main{
    public static void main(){
        List<long> inputNumbers = Arrays.asList(0L, 3435L, 35464L, 4645L);
        /* we want to calulate the
Utilize multithreading and to delegate calculation 
of each number of factorial to different thread this way we can calculate 
all the numbers factorial in parallel

        */
        List<FactorialThread> threads = new ArrayList<>();
        for(long inputNumber : inputNumbers){
            threads.add(new FactorialThread(inputNumber));
        }
        for(Thread thread : threads){
            thread.start();//[1st] Factorial threads started execution
        }  
        //so below lines of code will resolve race condition between [1st] and [2nd]
        for(Thread thread : threads){
            thread.join();
            //we can let main thread to wait for specific time 
            //Threads may take unreasonably long time
            //Always use the thread.join() with a time limit
            //Stop the thread if it's not done in time

        }

Perfomance
Criteria/definintion
Performance in Multithreaded applications

Performance can be defined in many ways depending on the use case.
Multithreaded applications performance criteria:
Latency- The time to completion of a task. Measusred in times units.
Throughput- The amount of tasks completed in a given period. Measured in tasks/time unit

Latency: