Four ways to create threads in java

Let's first look at processes and threads
Process is the smallest unit of computer scheduling resources
Thread is the smallest unit of process scheduling resources. A process has at least one thread

Four ways to create threads in java

1. Inherit the Thread class and override the run() method. The run method is the task to be executed

Advantage: it's simple and direct
Disadvantages: one class cannot inherit more than one class, which is highly coupled. First, create a MyTHread1 class, which inherits from the Thread class, then rewrite the run method in the Thread class, and output the name and address of the Thread 100 times in the run method

class MyThread1 extends Thread{
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("Hello");			
		}
	}
}

Create the MyThread1 object in the main function and call the start() method to start the thread

Thread thread1 = new MyThread1();
thread1.start();

2. Implement the Runnable interface and rewrite the run method, which is the task to be executed

Advantages: the task is separated from other tasks, reducing the coupling
First, create the Mythread2 class, implement the Runnable interface, rewrite the run method, and output hello 100 times in the run implementation
world

class MyThread2 implements Runnable{

	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("hello world");
		}
	}
}

Create the object of MyThread2 in the main function. Because the Runnable interface is used here, you need to create a new thread first, and then call the start method to start the thread

Runnable thread2 = new MyThread2();
new Thread(thread2).start();

Note: if the run() method in the class is called directly in the main function, the main thread is used instead of the thread created by yourself. In this case, it is meaningless to create a thread, so you need to use start to start the thread

Next, we start two threads simultaneously in the same main method

Thread thread1 = new MyThread1();
		
		/*
		 * start();Start thread
		 * Open up a new thread task
		 */
thread1.start();
		
Runnable thread2 = new MyThread2();
new Thread(thread2).start();
		/*
		 * The run method is executed directly with the main thread
		 */
		//thread1.run();

We will find that the output will cross. That is to say, when thread 1 executes and outputs part of the name and hello of thread 1, thread 2 will execute and output helloworld. The reason for this is that thread 1 runs out of cpu time slice after using cpu time slice to execute part of the output. It is thread 2's turn to use cpu time slice

The following is the complete code of the first two methods,

public class ThreadDemo1 {
	public static void main(String[] args) {
		Thread thread1 = new MyThread1();
		
		/*
		 * start();Start thread
		 * Open up a new thread task
		 */
		thread1.start();
		
		Runnable thread2 = new MyThread2();
		new Thread(thread2).start();
		
		//The reason for the crossover is that the cpu time slice has run out
		
		/*
		 * The run method is executed directly with the main thread
		 */
		//thread1.run();
	}
}
//Create Thread 1 to inherit Thread class
class MyThread1 extends Thread{
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("Hello");			
		}
	}
}

//Create thread 2 to implement Runnable interface
class MyThread2 implements Runnable{
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("hello world");
		}
	}
}

3. Implement the Callable interface and rewrite the call() method. The call is the thread task

First, create a MyCallable class to implement the Callable interface and rewrite the call() method. The Callable interface supports generics. In order not to report a warning, you need to add a data type when implementing it
The sleep() method is to make the thread enter the sleep state (i.e. blocking state) for a certain time, and then enter the ready state

class MyCallable implements Callable<String>{
	@Override
	public String call()  {
		System.out.println("Hello");
		return "End of task execution";
	}	
}

The difference between the first three methods is that they inherit the Thread class and implement the Runnable interface, rewrite the run() method and implement the Callable interface, rewrite the call() method, and the run method has no return value. The call method has a return value, so we can use the third method when we need the task to have a return value

4. Create a thread using a thread pool

The concept of thread pool: a collection of idle threads
Role of thread pool: it improves efficiency and reduces the time of thread creation and shutdown
The Executors class is used to create a thread pool. You can create a thread pool by calling the methods in the class
There are four ways to create a thread pool

(1) . create thread pool based on memory: executors newCachedThreadPool()

Advantages: unlimited threads can be stored
Disadvantages: too much memory

First, create a thread pool based on memory

ExecutorService pool = Executors.newCachedThreadPool();

Call the execute method to give the thread pool a task: output the name of the thread executing the task
Two tasks are created here
In the execute (command) method, the parameter contains the task to be executed. The creation of the task can be written into the run method in the Runnable interface using the method of the anonymous inner class, or the lambda expression can be used

public class ThreadPoolDemo01 {
	public static void main(String[] args) {
		//Create a thread pool according to memory, which can have unlimited threads
		ExecutorService pool = Executors.newCachedThreadPool();
		pool.execute(new Runnable() {
			public void run() {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName());
				
			}
		});
		
		pool.execute(()->{
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName());
		});
		//Close thread pool
		pool.shutdown();
	}
}

Output results

(2) Create a fixed size thread pool: executors Newfixedthreadpool (number of threads)

The number of threads is fixed. When multiple tasks enter the thread pool, if there are no idle threads, the tasks entering later will wait for the execution of the previous tasks before the threads are idle

Create a thread pool with only 3 threads

ExecutorService pool = Executors.newFixedThreadPool(3);

Then give 10 tasks to the thread pool, output which thread executes the task every 100 milliseconds, and close the thread pool after it is used up

for(int i=0;i<10;i++) {
	pool.execute(()->{
		try {
			Thread.sleep(100);
			System.out.println(Thread.currentThread().getName()+":Perform tasks");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	});
	//Close thread pool
	pool.shutdown();
}

result:

(3) The third method also creates a fixed size thread pool, but this thread pool supports delayed and periodic tasks: executors Newscheduledthreadpool (number of threads)

Create a thread pool with only three threads

ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);

Note that the return value type here should be ScheduledExecutorService

The schedule(command, delay, unit) method is used to create deferred threaded tasks
command: thread task, which is the call method task in Callable;
Delay: delay time, that is, the task starts executing after the specified time;
Unit: time unit, the unit of a given delay time, using the attribute in the TimeUnit class

pool.schedule(()->{
	//Output the name of the thread executing the task
	System.out.println(Thread.currentThread().getName());
}, 1, TimeUnit.SECONDS);

Schedule at fixed rate (command, initial delay) is used to create periodic tasks,
period, unit) method
command: thread task
initialDelay: delay time (how long after the first task is executed)
period: cycle time (how often the task is executed)
Unit: time unit

pool.scheduleAtFixedRate(()->{
	System.out.println(Thread.currentThread().getName());
}, 1, 3, TimeUnit.SECONDS);

Note: the thread pool cannot be closed for periodic tasks, otherwise it will have no effect

(4) Create a single threaded thread pool: executors newSingleThreadExecutor()

The characteristic of single thread pool is that the tasks executed are in order, first come, first executed, and then executed

public static void main(String[] args) {
	//Create a thread pool for a thread that executes in sequence
	ExecutorService pool = Executors.newSingleThreadExecutor();
	for(int i=0;i<5;i++) {
		pool.execute(()->{
			try {
				Thread.sleep(100);
				System.out.println(Thread.currentThread().getName());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});
	}
	//Close thread pool
	pool.shutdown();
}

Tags: Java Multithreading thread

Posted by RwpTechAdMin on Wed, 11 May 2022 05:17:27 +0300