Skip to content

Instantly share code, notes, and snippets.

@yclim95
Last active May 14, 2019 23:54
Show Gist options
  • Save yclim95/b17af7623b45a1bd46b04342fffa4941 to your computer and use it in GitHub Desktop.
Save yclim95/b17af7623b45a1bd46b04342fffa4941 to your computer and use it in GitHub Desktop.
Java MultiThreading Part IV

#Java MultiThreading Part IV

##Lesson 12 : Callable & 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.

###1. Simple Way

App.java

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 * Callable & Future
 */
public class App {

	public static void main(String[] args) {
		ExecutorService executor = Executors.newCachedThreadPool();
		
		executor.submit(new Runnable(){

			@Override
			public void run() {
				Random random = new Random();
				int duration = random.nextInt(4000);
				
				System.out.println("Starting....");
				try {
					Thread.sleep(duration);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				System.out.println("Finish....");
			}
			
		});
		
		executor.shutdown();
	}//ENDof Main()
}

OUTPUT

Starting....
Finish....

###2. Use Callable & Future

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;

/*
 * Callable & Future
 */
public class App {

	public static void main(String[] args) {
		ExecutorService executor = Executors.newCachedThreadPool();
		
		//Callable & Future
		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("Starting....");
				try {
					Thread.sleep(duration);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				System.out.println("Finish....");
				
				return duration;
			}
			
		});
		
		executor.shutdown();
		try {
			System.out.println("Result: " + future.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}//ENDof Main()
}

OUTPUT

Starting....
Finish....
Result: 3672

###3. Throw Exception for Callable

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;

/*
 * Callable & Future
 */
public class App {

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

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

OUTPUT

java.io.IOException: Sleeping for too long

##Lesson 13 : Interrupting Threads (InterruptedExceptions)

import java.util.Random;

/*
 * Interrupting Threads
 */
public class App {

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

			@Override
			public void run() {
				Random random = new Random();
				
				// 1E10 => 1 x (10 ^ 6)
				for(int i = 0; i < 1E8; i++){
					
					//Check if is being interrupted
					if ( Thread.currentThread().isInterrupted() ){
						System.out.println("Interrupted!!!");
						break;
					}
					
					/*try{
						Thread.sleep(1);
					}catch(InterruptedException e){
						System.out.println("Interrupted!!!");
						break;
					}*/
					Math.sin(random.nextDouble());
				}
			}
			
		});
		
		t1.start();
		
		Thread.sleep(500);
		//Set Flag tells that it is being interrupted
		//Does not terminate 
		t1.interrupt(); 
		
		t1.join();
		
		System.out.println("Finished...");
	}//ENDof Main()

}

OUTPUT

Starting...
Interrupted!!!
Finished...

##Lesson 14 : MultiThreading in Swing with (SwingWorker)

App.java

import javax.swing.SwingUtilities;


public class App {

    /**
     * @param args
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            
            @Override
            public void run() {
                new MainFrame("SwingWorker Demo");
            }
        });
    }

}

MainFrame.java

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

public class MainFrame extends JFrame {

    private JLabel countLabel1 = new JLabel("0");
    private JLabel statusLabel = new JLabel("Task not completed.");
    private JButton startButton = new JButton("Start");

    public MainFrame(String title) {
        super(title);

        setLayout(new GridBagLayout());

        GridBagConstraints gc = new GridBagConstraints();

        gc.fill = GridBagConstraints.NONE;

        gc.gridx = 0;
        gc.gridy = 0;
        gc.weightx = 1;
        gc.weighty = 1;
        add(countLabel1, gc);

        gc.gridx = 0;
        gc.gridy = 1;
        gc.weightx = 1;
        gc.weighty = 1;
        add(statusLabel, gc);

        gc.gridx = 0;
        gc.gridy = 2;
        gc.weightx = 1;
        gc.weighty = 1;
        add(startButton, gc);

        startButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                start();
            }
        });

        setSize(200, 400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    private void start() {
        
        // Use SwingWorker<Void, Void> and return null from doInBackground if
        // you don't want any final result and you don't want to update the GUI
        // as the thread goes along.
        // First argument is the thread result, returned when processing finished.
        // Second argument is the value to update the GUI with via publish() and process()
        SwingWorker<Boolean, Integer> worker = new SwingWorker<Boolean, Integer>() {

            @Override
            /*
             * Note: do not update the GUI from within doInBackground.
             */
            protected Boolean doInBackground() throws Exception {
                
                // Simulate useful work
                for(int i=0; i<30; i++) {
                    Thread.sleep(100);
                    System.out.println("Hello: " + i);
                    
                    // optional: use publish to send values to process(), which
                    // you can then use to update the GUI.
                    publish(i);
                }
                
                return false;
            }

            @Override
            // This will be called if you call publish() from doInBackground()
            // Can safely update the GUI here.
            protected void process(List<Integer> chunks) {
                Integer value = chunks.get(chunks.size() - 1);
                
                countLabel1.setText("Current value: " + value);
            }

            @Override
            // This is called when the thread finishes.
            // Can safely update GUI here.
            protected void done() {
                
                try {
                    Boolean status = get();
                    statusLabel.setText("Completed with status: " + status);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            }
            
        };
        
        worker.execute();
    }
}
 

##Resources

  1. Back to JAVA MultiThreading Part III
  2. Main Contents
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment