import java.lang.Thread.State;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

/**
 * {@link <a href=
 * "https://[Log in to view URL]"
 * target= "_blank">Multi-threading</a>}
 * 
 * @author itammb ( Italia Massimiliano Buscati )
 * @version JDK 1.15
 *
 */
class Main {
	private static class PrintThread extends Thread {
		@Override
		public void run() {
			try {
				System.out.println("Thread -> " + this.getId() + " sta elaborando");
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				System.out.println("Thread -> " + this.getId() + " ha terminato");
			}
		}
	}

	private static class PrintRunnable implements Runnable {
		private Thread thread;

		public void setThread(Thread thread) {
			this.thread = thread;
		}

		@Override
		public void run() {
			try {
				System.out.println("Thread " + thread.getId() + " sta elaborando");
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				System.out.println("Thread -> " + thread.getId() + " ha terminato");
			}
		}
	}
	
	private static class StateRunnable implements Runnable {
		private Thread thread;

		public void setThread(Thread thread) {
			this.thread = thread;
		}

		@Override
		public void run() {
			try {
				Thread.sleep(150);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(
					"Thread -> " + Thread.currentThread().getId() + " riprende dopo Thread.sleep(long millis)");
			System.out.println("Thread -> " + thread.getId() + " - " + thread.getState());

			Thread.yield();
			System.out.println("Thread -> " + Thread.currentThread().getId() + " riprende dopo Thread.yield()");
		}
	}

	private static class StateOtherRunnable implements Runnable {
		private Thread thread;

		public void setThread(Thread thread) {
			this.thread = thread;
		}

		@Override
		public void run() {

			System.out.println("Thread -> " + thread.getId() + " - " + thread.getState());
			System.out.println("Thread -> " + thread.getId() + " - " + thread.getState());

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

			System.out.println(
					"Thread -> " + Thread.currentThread().getId() + " riprende dopo Thread.sleep(long millis)");
		}
	}
	
	private static class MasterThread extends Thread {
		private final List<ThreadChild> buffer = new ArrayList<ThreadChild>();
		
		public List<ThreadChild> getBuffer() {
			return buffer;
		}
		
		@Override
		public void run() {
			System.out.println("Thread main -> " + getName());
			System.out.println("Thread main -> " + getPriority());
						
			for (int i = 0; i < 4; i++) {
				ThreadChild threadChild = new ThreadChild();
				buffer.add(threadChild);
				threadChild.start();
			}
		}
		
		public MasterThread() {
			super();
			
			setName("ITALO");
			setPriority(Thread.MAX_PRIORITY);
		}
	}
	
	private static class ThreadChild extends Thread {		
		@Override
		public void run() {
			System.out.println("Thread child -> " + getName());
			
			try {
				Thread.sleep(10000000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		public ThreadChild() {
			super();	
			
			setPriority(Thread.MIN_PRIORITY);
		}
	}
	
	private static class GenericThread extends Thread
	{
		@Override
	    public void run()
	    {
	        if( Thread.currentThread().isDaemon() )
	            System.out.println( getName() + " -> è un thread-daemon" );	          
	        else
	            System.out.println( getName() + " -> è un thread-user" );
	    }
	    
	    public GenericThread( String name ){ super( name ); }
	}
	
	private static class UniTestMultyThreds {

		/**
		 * @see Thread#currentThread()
		 * @see Thread#getId()
		 * 
		 */
		public void applayThread() {

			for (int i = 0; i < randInt(1, 7); i++) {
				PrintThread print = new PrintThread();
				print.start();
			}
		}

		/**
		 * @see Runnable
		 * @see Thread#getId()
		 * 
		 */
		public void applayRunnable() {

			for (int i = 0; i < randInt(1, 7); i++) {
				PrintRunnable runnable = new PrintRunnable();
				Thread print = new Thread(runnable);
				runnable.setThread(print);
				print.start();
			}
		}

		/**
		 * @see Thread#sleep(long)
		 * @see Thread#join()
		 * 
		 */
		public void showState() throws InterruptedException {
			StateRunnable runnable = new StateRunnable();
			Thread state = new Thread(runnable);

			StateOtherRunnable runnableOther = new StateOtherRunnable();
			Thread stateOther = new Thread(runnableOther);

			// quando un thread acquisisce il token stampa lo stato del altro
			runnable.setThread(stateOther);
			runnableOther.setThread(state);

			whoIs(state, stateOther);

			state.start();
			stateOther.start();

			whoIs(state, stateOther);

			// il flusso rimane in attesa fino a quando i due thread sono stato TERMINATED
			state.join();
			stateOther.join();

			whoIs(state, stateOther);
		}

		private void whoIs(Thread threadState, Thread threadStateOther) {
			System.out.println("Thread -> " + threadState.getId() + " - " + threadState.getState());
			System.out.println("Thread -> " + threadStateOther.getId() + " - " + threadStateOther.getState());
		}

		/**
		 * @see Thread#getName()
		 * @see Thread#getPriority()
		 * @see Thread#yield()
		 * @see Thread#interrupt()
		 * 
		 */
		public void showChild() {
			
			MasterThread masterThread = new MasterThread();
			List<ThreadChild> childThreads = masterThread.getBuffer();
			
			masterThread.start();		
			while(! masterThread.getState().equals(State.TERMINATED))
			{
				Thread.yield();
				System.out.println("Thread main -> " + masterThread.getState());
			}
			
			shoutdown(childThreads);
		}
		
		private void shoutdown(List<ThreadChild> childThreads) {
						
			boolean notShoutdown= true;
			while (notShoutdown)
			{
				Iterator<ThreadChild> iter = childThreads.iterator();
				
				while(iter.hasNext() ) {
					ThreadChild threadChild = iter.next();
				
					if (! threadChild.getState().equals(State.TERMINATED))
					{
						threadChild.interrupt();
						notShoutdown = true;
					} else
						notShoutdown = false;
				}
			}
		}
		
		/**
		 * @see Thread#setDaemon(boolean)
		 * 
		 */
		public void isDaemonThread() {
			GenericThread thread_1 = new GenericThread( "thread_1" );
			GenericThread thread_2 = new GenericThread( "thread_2" );
			GenericThread thread_3 = new GenericThread( "thread_3" );

			thread_1.setDaemon( true );
			thread_3.setDaemon( true );
			
			thread_1.start();     
			thread_2.start();			
			thread_3.start();  
		}
					
		private int randInt(int min, int max) {
			return new Random().nextInt((max - min) + 1) + min; // range tra min..max ( incluso ) dove max > min
		}
	}

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

		// Unit test - estensione della classe Thread
		new UniTestMultyThreds().applayThread();
		
		// Unit test - implementazione dell'interfaccia Runnable
		// new UniTestMultyThreds().applayRunnable();
		
		// Unit test - due thread che stampano lo stato del altro, reciprocamente
		// new UniTestMultyThreds().showState();
			
		// Unit test - lancio e chiusura di n thread-child
		// new UniTestMultyThreds().showChild();
			
		// Unit test - verifica la natura di un thread
		// new UniTestMultyThreds().isDaemonThread();
	}
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: