Mode 1. Inheritance of Thread classes
- Inherit Thread and override the run() method in this class. The run() method is the specific business that the thread will implement.
public class NewThread1 extends Thread{ private String title; public NewThread1(String title){ this.title = title; } @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(this.title+",i="+i); } } }
How to start a thread?
- You cannot call run() method directly when starting a thread
Let's first look at what happens when you call the run() method directly:
public class ThreadMain { public static void main(String[] args) { NewThread1 thread1 = new NewThread1("Thread1"); NewThread1 thread2 = new NewThread1("Thread2"); NewThread1 thread3 = new NewThread1("Thread3"); thread1.run(); thread2.run(); thread3.run(); } }
By intercepting some of the results, it can be seen that the direct call to run() method is only a sequential printing, and does not use multithreading.
- The correct way to start multithreading is to call the start() method of the Thread class
public class ThreadMain { public static void main(String[] args) { NewThread1 thread1 = new NewThread1("Thread1"); NewThread1 thread2 = new NewThread1("Thread2"); NewThread1 thread3 = new NewThread1("Thread3"); thread1.start(); thread2.start(); thread3.start(); } }
From the observations, it can be seen that the start() method is called to start the thread:
The difference and relationship between start() method and run() method:
-
The start method is called to start the thread, and the run method is only a normal method call of thread, or it is executed in the main thread. So, calling the start method to achieve multithreading, while calling the run method does not achieve multithreading
-
Start:
Start method is used to start threads, and multithreading is realized. At this time, the following code can be executed directly without waiting for the run method body code to be executed. By calling the start () method of the Thread class to start a thread, the thread is in a ready (runnable) state and does not run. Once the spu time slice is obtained, the run () method is executed. Here, the method run () is called the thread body. It contains the content of the thread to be executed. The Run method runs the end. Bundle, and the thread terminates. -
Run:
Run () method is just a common method of class. If the Run method is called directly, there is still only one thread in the program, the main thread, the execution path of the program is still only one thread, or the execution path should be sequential, or the following code can be executed only after the run method body has been executed, which is not achieved. The purpose of writing threads.
How does start() call the run() method when multithreading is started? (Brief)?
1. By looking at the source code of the start() method, you can see that the start() method calls a start0() method. The start0() method is a declared but unrealized method, which is defined by using the native keyword (referring to calling native system functions).
2. By observing the local method registerNative, you can see that the start() method calls the start0() method, which actually calls the JVM_StartThread method.
3. The macro JVM_ENTER defines the JVM_StartThread method. The function creates a real platform-related local thread, whose thread function is thread_enter.
4. thread_enter calls a vmSymbolHandles::run_method_name() method.
5. run_method_name is defined as macro in vmSymbols.hpp:
class vmSymbolHandles: AllStatic { ... template(run_method_name,"run") ; ... }
You can see that the sentence template(run_method_name,"run") calls the run method.
Mode 2. Implementing Runnable() Interface
public class NewThread2 implements Runnable{ private String title; public NewThread2(String title){ this.title = title; } @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(this.title+",i="+i); } } }
How to start a thread?
Start mode 1:
The construction method public Thread(Runnable target) provided by the Thread class can accept Runnable interface objects.
public class ThreadMain { public static void main(String[] args) { NewThread2 thread1 = new NewThread2("Thread1"); NewThread2 thread2 = new NewThread2("Thread2"); NewThread2 thread3 = new NewThread2("Thread3"); Thread th1 = new Thread(thread1); Thread th2 = new Thread(thread2); Thread th3 = new Thread(thread3); th1.start(); th2.start(); th3.start(); //Or: //new Thread(thread1).start(); //new Thread(thread2).start(); //new Thread(thread3).start(); } }
Startup Mode 2: Anonymous Internal Class Startup
public class ThreadMain { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("thread1"); } }).start(); } }
Startup Mode 3: Lamdba Expressions for Runnable Object Creation
public class ThreadMain { public static void main(String[] args) { Runnable runnable = ()-> System.out.println("thread2"); new Thread(runnable).start(); } }
Mode 3. Implement Callable interface:
The Callable interface is used to implement multithreading when a return value is needed.
- Implementing Callable Interface and Overwriting call Method
- Future interface: Accepts the return value of the Callable interface (which appears in pairs with Callable)
-
- The get method in the Future interface blocks the current thread until the return value of Callable is obtained
import java.util.concurrent.Callable; public class NewThread3 implements Callable { private int ticket = 20; @Override public Object call() throws Exception { while(this.ticket>0){ System.out.println("Surplus"+ticket--+"Tickets!"); } return "Tickets are sold out!"; } }
Start multithreading:
import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class ThreadMain { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> task = new FutureTask(new NewThread3()); new Thread(task).start(); new Thread(task).start(); //Output return value System.out.println(task.get()); } }
Mode 4. Thread pool creation multithreading:
You can click to see the detailed introduction and analysis: The Principle and Application of Thread Pool
Create a thread pool:
Create a thread pool based on the parameters of ThreadPoolExecutor class of the thread pool:
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 2000, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<Runnable>());
Submit tasks to the thread pool:
There are two ways to submit tasks to the thread pool: execute() and submit() methods
The execute() method submits tasks to the thread pool:
The execute() method is used to submit tasks that do not require a return value, so it is not possible to determine whether the task was successfully executed by the thread pool.
import java.util.concurrent.*; class RunnableThread implements Runnable{ @Override public void run() { for (int i = 0; i < 50; i++) { System.out.println(Thread.currentThread().getName()+","+i); } } } public class ThreadMain { public static void main(String[] args){ RunnableThread runnableThread = new RunnableThread(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 2000, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<Runnable>()); for (int i = 0; i < 5; i++) { threadPoolExecutor.execute(runnableThread); } } }
The submit() method submits tasks to the thread pool:
The submit() method is used to submit tasks requiring return values. The thread pool returns a future-type object through which the task can be judged to be successful, and the return value can be obtained by the get() method of the future, which blocks the current thread until the task is completed, while using the get (long timeout, TimeUnit unit) method blocks the current thread. Return immediately after a period of time, when the task may not be completed.
import java.util.concurrent.*; class CallableThread implements Callable<String>{ @Override public String call() throws Exception { for (int i = 0; i < 50; i++) { System.out.println(Thread.currentThread().getName()+","+i); } return Thread.currentThread().getName()+"Completion of tasks"; } } public class SubmitTest { public static void main(String[] args) { CallableThread callableThread = new CallableThread(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 2000, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<Runnable>()); for (int i = 0; i < 5; i++) { Future<String> future = threadPoolExecutor.submit(callableThread); String str = null; try { str = future.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println(str); } } }
Close the thread pool:
You can close the thread pool by calling the shutdown or shutdownNow method of the thread pool.
threadPoolExecutor.shundown();
or
threadPoolExecutor.shundown();