31-Java multithreaded programming

Java multithreaded programming

The biggest feature in Java is the support for multi-threaded development. Therefore, in the entire Java technology, if you cannot have a comprehensive and detailed understanding of the concept of multi-threading, serious problems will occur in the project design process, especially in the process of concurrent access. Technical flaws.

Process and thread

If you want to understand threads, you must first understand the concept of processes. In the traditional DOS era, its own characteristics: if a virus appears, then all programs cannot be executed because DOS uses a single process. The biggest feature of single-process processing: only one program is allowed to execute at the same time period.
Windows has opened a multi-process design, which means that multiple programs can be run at the same time in a period of time, and these programs will take turns to preempt resources. Multiple programs will be executed in sequence at the same time period, but only one process will be executed at the same time point. With a multi-core CPU, since there are more CPUs that can be processed, even if there are more processes appearing, The processing speed can be improved than that of a single-core CPU.
Thread: It is a smaller program unit divided on the basis of the process. The thread is created and used on the basis of the process. Therefore, the thread depends on the support of the process. However, the startup speed of the thread is much faster than the process, so multithreading is used for concurrency. When processing, the performance of its execution is higher than that of the process.
Java is a multi-threaded programming language, so Java can get higher performance when performing concurrent access processing.

Inherit the Thread class to achieve multi-threading

To implement the definition of multithreading in Java, a special thread main class is needed to define the execution tasks of the thread. The definition of this main class is required, and it can be completed only by implementing a specific interface or inheriting a specific parent class .
There is a java.lang.Thread program class provided in Java. As long as this class is inherited as the main class of thread, it does not mean that this class can directly implement multi-threading, because one needs to be overwritten in the Thread class. Run method, this method belongs to the main method of the thread.
Multithreaded main class

class MyThread extends Thread{
    
    		//实现线程的主体类,
	private String title;
	public MyThread(String title) {
    
    
		this.title = title;
	}
	@Override
	public void run() {
    
    		//线程的主体方法
		for(int x = 0; x<10; x++) {
    
    
			System.out.println(this.title +"运行,x="+ x);
		}
	}
}

The functions to be executed by multiple threads should be defined in run(). What needs to be explained is: if you want to use a method in a class under normal circumstances, you must generate an instantiated object and then call the method in the class, and the run method cannot be called directly. This involves resource scheduling issues, and you want to start Multithreading must **use the start()** method.
Although the start method is called, the final execution is the run() method, and all thread objects are executed alternately, butThe order of execution is not controllable.
Question : Why not use run directly but must use the start method in the Thread class?
An "IllegalThreadStateException" exception class object will be thrown in start(), but the program has not processed it because the exception is RunTimeException or the like.
Object of each thread classOnly allowed to start once, This exception will be thrown if restarted repeatedly.

MyThread mt = new MyThread("线程A");
mt.start();
mt.start();		//错误

Taking into account the needs of developers at different levels during the execution of Java programs, it supports local operating system function calls. This technology is called JNI, but it is not recommended. You can use this technology to use some operating systems provided The low-level function performs special processing. The start0() method provided in the Thread class means that this method needs to be implemented by different operating systems.
ru0Gu9.png
In any case, as long as multithreading is defined, there is always only one solution for the start of multithreading: the start() method in the Thread class.

Runnable interface to achieve multi-threading

There is a single inheritance limitation for inheritance in Java, so a second multi-threaded definition structure is provided in Java: to implement the Java.lang.Runnable interface.

class MyThreadRun implements Runnable{
    
    		//实现线程的主体类,
	private String title;
	public MyThreadRun(String title) {
    
    
		this.title = title;
	}
	@Override
	public void run() {
    
    		//线程的主体方法
		for(int x = 0; x<10; x++) {
    
    
			System.out.println(this.title +"运行,x="+ x);
		}
	}
}
public class ThreadDemo {
    
    
	public static void main(String[] args) {
    
    
		Thread thRun = new Thread(new MyThreadRun("线程B"));		//Runnable实现
		thRun.start();
	}
}

But at this time, the Thread parent class is no longer inherited, and the start() method is no longer supported in the class. At this time, the Thread object is used to receive the Runnable object.
At this time, multi-threading can find that because only the Runnable interface object is implemented, there is no longer a single inheritance limitation on the thread main class at this time, and this design is a standard design.
Now Runnable is a functional programming interface, so you can directly use Lambda expressions to implement threads.

public class ThreadDemo {
    
    
	public static void main(String[] args) {
    
    
		for(int x=0;x<3;x++) {
    
    
			String title = "线程名称-"+x;
			Runnable run = ()->{
    
    
				for(int y = 0; y<10; y++) {
    
    
					System.out.println(title +"运行,y="+ y);
				}
			};
			new Thread(run).start();
		}
	}
}

In the future, multithreading will give priority to the implementation of Runnable, and always start multithreading through Thread class objects.

The relationship between Thread and Runnable

In terms of the code structure itself, it is most convenient to use Runnable, because it can avoid the limitation of single inheritance, and at the same time, it can better expand the function.
But from the structure, we also need to observe the connection between Thread and Runnable.
public class Thread Object implements Runnable{}
It is found that the Thread class is also a subclass of the Runnable interface, so when the Thread class was inherited, the run() method of the Runnable interface was overwritten.
rMETKJ.png
  In the multi-threaded design, the structure of the proxy design pattern is used. The user-defined thread subject knowledge is responsible for the realization of the core functions of the project, and all auxiliary implementations are handled by the Thread class.
  When Thread starts multithreading, the start() method is called, and then the run() method is found. When a Runnable interface object is passed through the constructor of the Thread class, the interface object will be saved by the target attribute in the Thread class. When the start() method is executed, the run() method in the Thread class is called, and this run() method calls the run() method that has been overwritten by the Runnable interface subclass.
  The essence of multi-threaded development is that multiple threads can preempt the same resource. Thread mainly describes threads, and the description of resources is done by Runnable. Example: Use the ticket-buying program to implement concurrent access to resources from multiple threads.
rMmEPx.png

class MyThreadRun implements Runnable{
    
    		//实现线程的主体类,
	private int ticket = 5;
	private String title;
	@Override
	public void run() {
    
    		//线程的主体方法
		for(int x = 0; x<100; x++) {
    
    
			if(this.ticket > 0 ) {
    
    
				System.out.println(this.title +"买票,余票="+ this.ticket --);
			}
		}
	}
}
public class ThreadDemo {
    
    
	public static void main(String[] args) {
    
    
		MyThreadRun mt = new MyThreadRun();
		new Thread(mt).start();			//第1个线程启动
		new Thread(mt).start();			//第2个线程启动
		new Thread(mt).start();			//第3个线程启动
	}
}

Memory analysis:
rMuKUA.png

Callable interface realizes multithreading

  In terms of the most traditional development, the implementation of multithreading must rely on Runnable, but the interface of Runnable has a shortcoming: a return value cannot be obtained after the thread is executed. So a new thread implementation interface is proposed after JDK1.5: java.util.concurrent.Callable.

@FunctionalInterface
public interface Callable<V>{
    
    
	public V call() throws Exception;
}

A generic type can be set when the definition of Callable is found, and the type of this generic type is the type of the returned data. In this way, the potential safety hazards caused by downward transformation can be avoided.
rM1Cpn.png
Example: Using Callable to achieve multi-threaded processing

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyThreadRun implements Runnable{
    
    		//实现线程的主体类,
	private int ticket = 5;
	private String title;
	@Override
	public void run() {
    
    		//线程的主体方法
		for(int x = 0; x<100; x++) {
    
    
			if(this.ticket > 0 ) {
    
    
				System.out.println(this.title +"买票,余票="+ this.ticket --);
			}
		}
	}
}
public class ThreadDemo {
    
    
	public static void main(String[] args) throws Exception{
    
    
		FutureTask<String> task = new FutureTask<>(new MyThreadCal());
		new Thread(task).start();
		System.out.println("线程返回数据" + task.get());
	}
}

Interview: Explain the difference between Runnable and Callable?

  • Runnable is a multi-threaded implementation interface proposed in Jdk1.0, and Callable is proposed by JDK1.5;
  • Only the run() method is provided in the Runnable interface and there is no return value;
  • Callable provides a call() method, which can have a return value;

Multi-threaded running status

  For multi-threaded development, the process of writing a program is always in accordance with: define the thread main class, and then start the thread through the Thread class, but it does not mean that you call the start() method, and the thread has already started running Because the overall thread processing has its own set of running states.
rMHFB9.png

  1. The object of any thread should be encapsulated with the Thread class, so the start of the thread uses start(), but when it is started, several threads will actually enter a ready state and are not executed now;
  2. After entering the ready state, you need to wait for resource scheduling. When a thread is successfully scheduled, it enters the running state (run() method), but all threads cannot be executed continuously, and some pause states need to be generated in the middle, such as Some threads need to give up resources after executing for a period of time, and then this thread will enter the blocked state and then return to the ready state.
    In fact, several threads will enter a ready state and are not executed now;
  3. After entering the ready state, you need to wait for resource scheduling. When a thread is successfully scheduled, it enters the running state (run() method), but all threads cannot be executed continuously, and some pause states need to be generated in the middle, such as Some threads need to give up resources after executing for a period of time, and then this thread will enter the blocked state and then return to the ready state.
  4. When the run() method is executed, the main task of the thread is actually ended, and you can directly enter the stop state at this time.

Guess you like

Origin blog.csdn.net/MARVEL_3000/article/details/111467397