
public class JoinExample {
	public static void main(String[] args) {
		final Thread thread1 = new Thread(new Runnable() {
			public void run() {
				System.out.println("Thread 1 Message 1");
				try {
					Thread.sleep(2000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread 1 Message 2");
			}
		});
		
		final Thread thread2 = new Thread(new Runnable() {
			public void run() {
				System.out.println("Thread 2 Message 1");
				try {
					Thread.sleep(4000);
				} catch (InterruptedException e) {
					System.out.println("Thread 2 Interrupted!");
				}
				System.out.println("Thread 2 Message 2");
			}
		});
		
		Thread thread3 = new Thread(new Runnable() {
			public void run() {
				System.out.println("Thread 3 Message 1");
				System.out.println("Number of active threads: " + Thread.activeCount());
				// Wait for thread 1 to finish execution.
				try {
					thread1.join();
				// Any method that waits must throw an InterruptedException.
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Thread 3 Message 2");
				
				System.out.println("Number of active threads: " + Thread.activeCount());
				
				int count = 0;
				while (thread2.isAlive()) {
					System.out.println("Waiting for thread 3 to finish");
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					if (count > 1) {
						System.out.println("Tired of waiting, interrupting thread 2");
						thread2.interrupt();
						count = 0;
					}
					count++;
				} 
				
				System.out.println("Thread 3 Message 3");
			}
		});
		
		thread2.start();
		thread1.start();
		thread3.start();

	}
}

