Showing posts with label MultiThreading. Show all posts
Showing posts with label MultiThreading. Show all posts

Saturday, September 6, 2014

14. Interrupting Threads

Java Multithreading: Interrupting Threads 
What exactly are those pesky InterruptedExceptions? In this video I show you how to interrupt running threads in Java using the built-in thread interruption mechanism.

Code For This Tutorial


import java.util.Random;

public class App {

      public static void main(String[] args) throws InterruptedException {
            System.out.println("Starting.");

            Thread t1 = new Thread(new Runnable() {
                  public void run() {
                        Random ran = new Random();

                        for (int i = 0; i < 1E8; i++) {
                              /*
                                if(Thread.currentThread().isInterrupted()){
                                System.out.println("Interrupted!"); break; }
                               */
                              try {
                                    Thread.sleep(1);
                              } catch (InterruptedException e) {
                                    System.out.println("Interrupted!");
                                    break;
                              }

                              Math.sin(ran.nextDouble());
                        }

                  }
            });

            t1.start();

            Thread.sleep(500);

            t1.interrupt();

            t1.join();

            System.out.println("Finished.");
      }

}

***************************************************

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class App {

    public static void main(String[] args) throws InterruptedException {

        System.out.println("Starting.");

        ExecutorService exec = Executors.newCachedThreadPool();

        Future<?> fu = exec.submit(new Callable<Void>() {

            @Override
            public Void call() throws Exception {
                Random ran = new Random();

                for (int i = 0; i < 1E8; i++) {

                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("Interrupted!");
                        break;
                    }

                    Math.sin(ran.nextDouble());
                }
                return null;
            }

        });
        
        exec.shutdown();
        
        
        Thread.sleep(500);
        
        exec.shutdownNow();
        //fu.cancel(true);
        
        exec.awaitTermination(1, TimeUnit.DAYS);
        
        System.out.println("Finished.");
    }

}

Output:
Starting.
Interrupted!

Finished.

13. Callable and Future

Java Multithreading: Callable and Future
How to use Callable and Future in Java to get results from your threads and to allow your threads to throw exceptions. Plus, Future allows you to control your threads, checking to see if they’re running or not, waiting for results and even interrupting them or descheduling them.

Code For This Tutorial
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import java.util.concurrent.Future; 


public class App {

    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        
        Future<Integer> future = executor.submit(new Callable<Integer>() {

            @Override
            public Integer call() throws Exception {
                Random random = new Random();
                int duration = random.nextInt(4000);
                 System.out.println(duration);
                if(duration > 2000) {
                    throw new IOException("Sleeping for too long.");
                }
                
                System.out.println("Starting ...");
                
                try {
                    Thread.sleep(duration);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
                System.out.println("Finished.");
                
                return duration;
            }
            
        });
        
        executor.shutdown();
        
        try {
            System.out.println("Result is: " + future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            IOException ex = (IOException) e.getCause();
            
            System.out.println(ex.getMessage());
        }
    }


}

Output:
Starting ...
Finished.
Result is: 792

12. Semaphores

Java Multithreading: Semaphores
A tutorial on semaphores in Java. Semaphores are mainly used to limit the number of simultaneous threads that can access a resources, but you can also use them to implement deadlock recovery systems since a semaphore with one permit is basically a lock that you can unlock from other threads. In this video we’ll take a look at the most important methods of the Semaphore class, and I’ll also show you an example of limiting the number of “connections” that threads can make simultaneously.

Code For This Tutorial

Connection.java: shows how to limit ‘connections’ with a semaphore

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

class Connection {

    private static Connection instance = new Connection();

    private Semaphore sem = new Semaphore(20, true);

    private int connections = 0;

    private Connection() {

    }

    public static Connection getInstance() {
        return instance;
    }

    public void connect() {
        try {
            sem.acquire();
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        try {
            doConnect();
        } finally {

            sem.release();
        }
    }

    public void doConnect() {

        synchronized (this) {
            connections++;
            System.out.println("Current connections: " + connections);
        }

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        synchronized (this) {
            connections--;
        }

    }
}

App.java: creates 200 threads and fires them off simultaneously. They all try to run the connect() method of the Connection class at the same time.

public class App {
       
    public static void main(String[] args) throws Exception {
        
        ExecutorService executor = Executors.newCachedThreadPool();
        
        for(int i=0; i < 200; i++) {
            executor.submit(new Runnable() {
                public void run() {
                    Connection.getInstance().connect();
                }
            });
        }
        
        executor.shutdown();
        
        executor.awaitTermination(1, TimeUnit.DAYS);
    }

}


Output:
Current connections: 1
Current connections: 2
Current connections: 3
Current connections: 4
Current connections: 5
Current connections: 6
Current connections: 7
Current connections: 8
Current connections: 9
Current connections: 10
Current connections: 9
Current connections: 9
Current connections: 9
Current connections: 10
Current connections: 10
Current connections: 9
Current connections: 7
Current connections: 8
Current connections: 9
Current connections: 10

11. DeadLock

Java Multithreading: Deadlock
The causes of deadlock and two things you can do about it. This video also covers how to write a method that can safely acquire any number of locks in any order without causing deadlock, using the tryLock() method of ReentrantLock.

Code For This Tutorial

The main program just runs the firstThread() and secondThread()methods in different threads. finish() is called after both threads finish.
The Runner class contains the synchronization code.

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Runner {
    private Account acc1 = new Account();
    private Account acc2 = new Account();

    private Lock lock1 = new ReentrantLock();
    private Lock lock2 = new ReentrantLock();
    
    private void acquireLocks(Lock firstLock, Lock secondLock) throws InterruptedException {
        while(true) {
            // Acquire locks
            
            boolean gotFirstLock = false;
            boolean gotSecondLock = false;
            
            try {
                gotFirstLock = firstLock.tryLock();
                gotSecondLock = secondLock.tryLock();
            }
            finally {
                if(gotFirstLock && gotSecondLock) {
                    return;
                }
                
                if(gotFirstLock) {
                    firstLock.unlock();
                }
                
                if(gotSecondLock) {
                    secondLock.unlock();
                }
            }
            
            // Locks not acquired
            Thread.sleep(1);
        }
    }

    public void firstThread() throws InterruptedException {

        Random random = new Random();

        for (int i = 0; i < 10000; i++) {

            acquireLocks(lock1, lock2);

            try {
                Account.transfer(acc1, acc2, random.nextInt(100));
            } finally {
                lock1.unlock();
                lock2.unlock();
            }
        }
    }

    public void secondThread() throws InterruptedException {
        Random random = new Random();

        for (int i = 0; i < 10000; i++) {
            
            acquireLocks(lock2, lock1);

            try {
                Account.transfer(acc2, acc1, random.nextInt(100));
            } finally {
                lock1.unlock();
                lock2.unlock();
            }
        }
    }

    public void finished() {
        System.out.println("Account 1 balance: " + acc1.getBalance());
        System.out.println("Account 2 balance: " + acc2.getBalance());
        System.out.println("Total balance: "
                + (acc1.getBalance() + acc2.getBalance()));
    }
}

Output:
Account 1 balance: 13175
Account 2 balance: 6825
Total balance: 20000


The main program (just creates and runs two threads):
public class App {
       
   
    public static void main(String[] args) throws Exception {
        
        final Runner runner = new Runner();
        
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                try {
                    runner.firstThread();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                try {
                    runner.secondThread();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        
        t1.start();
        t2.start();
        
        t1.join();
        t2.join();
        
        runner.finished();
    }

}

And finally, the Account class implements a simple bank account type thing.
class Account {
    private int balance = 10000;

    public void deposit(int amount) {
        balance += amount;
    }

    public void withdraw(int amount) {
        balance -= amount;
    }

    public int getBalance() {
        return balance;
    }

    public static void transfer(Account acc1, Account acc2, int amount) {
        acc1.withdraw(amount);
        acc2.deposit(amount);
    }
}