First, the meaning
The purpose of multithreading is to improve the utilization efficiency of CPU resources. In a single-threaded application, the program must wait for the current task to complete before it can continue with the next task, the CPU is idle for the time it waits, and the use of multithreading reduces idle time.
Second, the main thread
When the Java program starts, the main thread starts running immediately. All other threads are generated from the main thread, and the main thread must be the last to end the execution, because it needs to perform various shutdown actions. You can obtain a reference to the main thread by CurrentThread the static method.
classSolution { Public Static voidMain (string[] args) {Thread T=Thread.CurrentThread (); System.out.println ("Current thread:" + t);//Thread[main,5,main] Try { for(inti = 0; I < 10; i++) {System.out.println (i); Thread.Sleep (500); } } Catch(Interruptedexception exc) {System.out.println ("Current thread Interrupted"); } }}
By default, the primary thread's name is main, and the priority is 5,main, which is also the name of the thread group to which the main thread belongs. A thread group is a data structure that controls the state of a thread as a whole.
Third, create the thread
Threads can be created by inheriting the thread class or implementing the Runnable interface.
When you implement the Runnable interface to create a thread, you only need to implement the Run method, the Run method defines the thread's code, and the thread ends with the Run method. After a new thread has been created, only the call to the Start method thread will run, essentially the Start method executing the call to the Run method. However, the Runnable interface only defines the Run method, and the code that executes the run class must take advantage of the thread instance.
When you extend the thread class to create threads, you must override the Run method or define an Runnable interface instance.
classThreadaextendsThread {@Override Public voidrun () {Try { for(inti = 0; I < 10; i++) {System.out.println (i); Thread.Sleep (500); } } Catch(Interruptedexception exc) {System.out.println (GetName ()+ "Interrupted"); }} Threada (String name) {Super(name); Start (); }}classThreadbImplementsRunnable {PrivateThread t; @Override Public voidrun () {Try { for(inti = 0; I < 10; i++) {System.out.println (i); Thread.Sleep (500); } } Catch(Interruptedexception exc) {System.out.println (T.getname ()+ "Interrupted"); }} threadb (String name) {T=NewThread ( This, name); T.start (); }}classSolution { Public Static voidMain (string[] args) {Threada TA=NewThreada ("A"); THREADB TB=NewTHREADB ("B"); }}
Four, waiting for the thread
When a thread takes a significant amount of time to operate, other threads need to wait for the thread to end before they can continue to fetch data. In this case, the join method of the thread can be called directly, and the program will stay at the call to the join method until the end of the thread that called the method continues to execute the subsequent code.
classMyThreadextendsThread {@Override Public voidrun () {Try { for(inti = 0; I < 10; i++) {System.out.println (i); Thread.Sleep (500); } } Catch(Interruptedexception exc) {System.out.println (GetName ()+ "Interrupted"); }} MyThread (String name) {Super(name); }}classSolution { Public Static voidMain (string[] args) {MyThread TA=NewMyThread ("Thread A"); MyThread TB=NewMyThread ("Thread B"); MyThread TC=NewMyThread ("Thread C"); Try{Ta.start (); Ta.join ();//stay until Ta endsTb.start (); Tb.join (1000);//after 1 seconds, no matter whether the TB is over or not, continue executing the following codeTc.start (); Tc.join ();//stay until TC ends}Catch(Interruptedexception exc) {System.out.println ("Thread interrupted"); } System.out.println ("Thread A is alive" +ta.isalive ()); System.out.println ("Thread B is alive" +tb.isalive ()); System.out.println ("Thread C is alive" +tc.isalive ()); }}
Five, priority
Java assigns a priority to threads, and the priority determines how a thread is handled relative to other threads. The priority is an integer, but the absolute value is meaningless. The priority of a thread must be between min_priority to max_priority and defined as a static constant in the threads. The priority determines when to switch from one running thread to the next, called a context switch. The following rules occur:
- Threads voluntarily abandon control. This can be caused by the Cheng of a line that is blocked before the control, hibernation, or re-I/O. When this occurs, other threads are checked, and the highest priority in the thread that is about to run gets CPU resources.
- Threads are replaced by higher-priority threads. A low-priority thread that does not give up control will be replaced by a high-priority thread whatever it is doing. As long as the high-priority thread runs, it supersedes the low-priority thread, called preemptive multitasking.
When a thread with the same priority competes for CPU resources, the CPU resources are automatically obtained in Windows in a circular fashion, and other threads with equal priority in other operating systems must voluntarily abandon control to run. In theory, higher-priority threads get more CPU time, and threads with the same priority should get the same CPU time, but different environments have different multitasking, and for security reasons, threads with the same priority should give up control every now and then to ensure that all threads have a chance to run in a non-preemptive operating system.
Six, synchronous
Multithreading enables programs to perform asynchronous behavior, so you must provide a way to force synchronization when needed. For example, when two threads communicate and share a complex data structure, when a thread writes data to the structure, it must prevent other threads from writing to the data structure, or there may be a conflict.
The key to synchronization is the monitor, which is the object used as a mutex. Only one thread can have a monitor at a given moment, and once the thread enters the monitor, which is the lock, all other threads must wait until the thread exits the monitor, and all other threads attempting to enter the lock monitor will be suspended. Each class in Java has its own implicit monitor, and the thread automatically enters the object's implicit monitor whenever the object's synchronization method is called.
classCallme {synchronized voidCall (String msg) {//Synchronization MethodSystem.out.print ("[" +msg); Try{Thread.Sleep (1000); System.out.println ("]"); } Catch(Interruptedexception exc) {System.out.println ("Callme interrupted"); } }}classCallerextendsThread {PrivateString msg; PrivateCallme Target; Caller (Callme target, String msg) { This. target =Target; This. msg =msg; Start (); } @Override Public voidrun () {Target.call (msg); }}classSolution { Public Static voidMain (string[] args) {Callme target=NewCallme (); Caller ObA=NewCaller (Target, "Caller A"); Caller ObB=NewCaller (Target, "Caller B"); Caller ObC=NewCaller (Target, "Caller C"); Try{oba.join (); Obb.join (); Obc.join (); } Catch(Interruptedexception exc) {System.out.println ("Caller interrupted"); } }}
But suppose a class does not design multithreading, that is, there is no synchronization method in the class. Since we are not the creator of the class and cannot access its source code, we cannot add the synchronized modifier to the methods in the class using the above method. You can then place the parts that need to be synchronized into the synchronized code block.
class extends Thread { private String msg; Private Callme Target; Caller (Callme target, String msg) { this. target = target; this. msg = msg; Start (); } @Override publicvoid run () { synchronized (target) { // Synchronizing code blocks Target.call (msg); }}}
Java notes: Multithreading