Multithreading
Thread related concepts
- Program
It is a set of instructions written in a certain language to complete a specific task.
Simply put: it's the code we wrote
-
process
- Process refers to a running program, such as QQ, which starts a process, and the operating system will allocate memory space for the process. When we use Xunlei, another process is started, and the operating system will allocate new memory space for Xunlei
- A process is an execution process of a program, or a running program. It is a dynamic process: it has its own process of emergence, existence and extinction
-
thread
- A thread is created by a process and is an entity of the process
- A process can have multiple threads
-
Other related concepts
- Single thread: only one thread is allowed to execute at the same time.
- Multithreading: multiple threads can be executed at the same time. For example, a qq process can open multiple chat windows at the same time, and a thunderbolt process can download multiple files at the same time.
- Concurrency: multiple tasks are executed alternately at the same time, resulting in the illusion of "seemingly simultaneous". In short, multitasking implemented by a single core CPU is concurrency.
- Parallel: multiple tasks are executed simultaneously at the same time. Multi-core cpu can realize parallel.
public static void main(String[] args) { Runtime runtime=Runtime.getRuntime(); //Gets the number of CPUs / cores of the current computer int cpuNums=runtime.availableProcessors(); System.out.println("Currently cpu number="+cpuNums); }
Basic use of threads
- There are two ways to create threads
There are two ways to use threads in java
- Inherit the Thread class and override the run method
Thread class
//1. When a class inherits the Thread class, it can be used as a Thread //2. We will rewrite the run method and write our own business code //3. The run thread class implements the run method of the Runnable interface class Cat extends Thread{ int times=0; @Override public void run() { while (true){ //The thread every second. Output "meow meow, I'm a kitten" on the console System.out.println("Meow meow, I'm a kitten"+(++times)); //Let the thread sleep for 1 second try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (times==80){ break;//When the times reaches 80, the thread exits while, and the thread exits } } } } public class Thread1 { public static void main(String[] args) { //Create a Cat object that can be used as a thread Cat cat = new Cat(); cat.start();//Start the thread - > the run method of cat will eventually be executed cat.run//The run method is an ordinary method. If a thread is not really started, the run method will be executed until it is completed //Note: when the main thread starts a word thread Thread-0, the main thread will not block and will continue to execute //At this time, the main thread and sub thread execute alternately } }
- start0() is a local method and a JVM call. The bottom layer is implemented in C/C + +. The real effect of multithreading is start0(), not run
- After the start() method calls the start0() method, the thread does not necessarily execute immediately, but just turns the thread into a runnable state. The specific execution time depends on the CPU, which is uniformly scheduled
Implement Runnable interface
- Implement the Runnable interface and rewrite the run method
- java is single inheritance. In some cases, a class may have inherited a parent class. At this time, it is obviously impossible to create a Thread by inheriting the Thread class method
- java designers provide another way to create threads by implementing the Runnable interface
class Dog implements Runnable{//Develop threads by implementing the interface Runnable int count=0; @Override public void run() { while (true){ System.out.println("The dog barked"+(++count)+Thread.currentThread().getName()); //Sleep for one second try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (count==10){ break; } } } } public static void main(String[] args) throws Exception{ Dog dog = new Dog(); //dog.start(); Start cannot be called here //Create the Thread object, put the dog object (Runnable) into the Thread Thread thread = new Thread(dog); thread.start(); }
//Thread agent class simulates a minimalist thread class class ThreadProxy implements Runnable{ private Runnable target=null;//Property, type Runnable @Override public void run() { if (target!=null){ target.run();//Dynamic binding (run type) } } public ThreadProxy(Runnable target) { this.target = target; } public void start(){ start0();//This method really implements the multithreading method } public void start0(){ run(); } }
- The difference between inheriting Thread and implementing Runnable
- From the design of java, there is no difference in creating threads by inheriting Thread or implementing Runnable interface. From the jdk help document, we can see that the Thread class itself implements Runnable
- The implementation of Runnable interface is more suitable for multiple threads sharing a resource, and avoids the limitation of single inheritance. It is recommended to use Runnable
Thread termination
- Basic description
- When the thread completes the task, it will exit automatically
- You can also use variables to control the exit of the run method to stop the thread, that is, the notification method
//Notification method class T extends Thread{ private int count=0; //Set a control variable private boolean loop=true; @Override public void run() { while (loop){ try { Thread.sleep(50);//Let the current thread sleep for 50ms } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("T In operation"+(++count)); } } public void setLoop(boolean loop) { this.loop = loop; } } public static void main(String[] args) throws Exception{ T t = new T(); t.start(); //If you want the main thread to control the termination of the t thread, you must modify the loop //Let t exit the run method, thus terminating the T thread - > notification mode //Let the main thread sleep for 10 seconds, and then notify t thread to exit System.out.println("main Thread sleep 10 s"); Thread.sleep(10*1000); t.setLoop(false); }
Common thread methods
-
Common methods group I
- setName / / set the thread name to be the same as the parameter name
- getName / / returns the name of the thread
- Start / / start the thread to execute; The bottom layer of the Java virtual machine calls the start0 method of the thread
- Run / / call the thread object run method
- setPriority / / change the priority of the thread
- getPriority / / get the priority of the thread
- Sleep / / sleep (pause) the currently executing thread within the specified number of milliseconds
- Interrupt / / interrupt the thread
-
Precautions and details
- The bottom layer of satrt will create a new thread and call run. Run is a simple method call and will not start a new thread
- Range of thread priorities
- Interrupt, which interrupts the thread, but does not really end the thread. All are typically used to interrupt dormant threads
- Sleep: the static method of the thread to make the current thread sleep
class T extends Thread{//Custom thread class @Override public void run() { while (true) { for (int i = 0; i < 100; i++) { //Thread. currentThread(). Getname (get the name of the current thread) System.out.println(Thread.currentThread().getName() + "Eat steamed stuffed bun" + i); } try { System.out.println(Thread.currentThread().getName() + "Dormant"); Thread.sleep(20000);//20 seconds } catch (InterruptedException e) { //When the thread executes an interrupt method, it will catch an exception and can add its own business code System.out.println(Thread.currentThread().getName() + "cover interrupt"); } } } } public static void main(String[] args)throws Exception{ T t = new T(); t.setName("Zhang San"); t.setPriority(Thread.MIN_PRIORITY); t.start();//Start child thread //The child thread prints 5hi, then interrupts, and the child thread sleeps for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("hi"+i); } System.out.println(t.getName()+"thread priority "+t.getPriority()); t.interrupt();//When the execution reaches this point, it will interrupt the sleep of the t thread }
- Common methods group II
- yield: the comity of threads. Give up the cpu and let other threads execute, but the time of comity is uncertain, so comity may not succeed
- join: queue jumping of threads. Once the thread that cuts the queue successfully cuts the queue, it must first complete all the tasks of the thread that cuts the queue
class T extends Thread{ @Override public void run() { for (int i = 01; i <=20; i++) { try { Thread.sleep(1000);//Sleep for 1 second } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("I ate it"+i+"steamed stuffed bun"); } } } public static void main(String[] args)throws Exception{ T t = new T(); t.start(); for (int i = 1; i <=20; i++) { Thread.sleep(1000); System.out.println("The main thread ate"+i+"steamed stuffed bun"); if (i==5){ System.out.println("The main thread lets the child thread eat first"); //Thread queue jumping //t.join();// This is equivalent to the T thread executing first Thread.yield();//Comity does not necessarily succeed System.out.println("When the child thread has finished eating, the main thread continues to eat"); } } }
- User thread and daemon thread
- User thread: also called worker thread, when the task of the thread is completed or the notification method ends
- Daemon thread: it generally serves the worker thread. When all user threads end, the daemon thread ends automatically
- Common daemon threads: garbage collection mechanism
class T extends Thread{ @Override public void run() { for (; ;) { try { Thread.sleep(1000);//Sleep for 1 second } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("hello"); } } } public static void main(String[] args)throws Exception{ T t = new T(); //If we want the main thread to end, the child thread will end automatically //Just set the child thread as the daemon thread t.setDaemon(true); t.start(); for (int i = 1; i <=10; i++) { Thread.sleep(1000); System.out.println("hi"+i); } }
Thread life cycle
Synchronized
-
Thread synchronization mechanism
- In multi-threaded programming, some sensitive data are not allowed to be accessed by multiple threads at the same time. At this time, synchronous access technology is used to ensure that at most one thread can access the data at any time to ensure the integrity of the data.
- It can also be understood as follows: thread synchronization, that is, when a thread is operating on memory, other threads cannot operate on the memory address. Other threads cannot modify the memory address until the thread completes the operation.
-
Synchronization specific method
- Synchronous code block
synchronized (object) {//The synchronization code can only be operated after obtaining the lock of the object. / / the synchronized code is required;}
- Synchronized can also be placed in the method declaration, indicating that the whole method is a synchronized method
public synchronized void m(String name){ //Code to be synchronized;}
- Explanation: it's like that a little friend closes (locks) the door before going to the toilet and comes out (unlocks) after finishing. Then other little friends can use the toilet
//Implement interface mode, Use synchronized to synchronize threads. Class sellticket implements runnable {private static int ticketnum = 100; / / let multiple threads share private boolean loop=true; / / control the run method variable public synchronized void sell() {/ / synchronize methods. At the same time, only one thread can execute the sell method if (ticketnum < = 0) {system. Out. Println ("end of ticket sales"); loop = false; return;} Try {thread. Sleep (50); / / sleep for 50 milliseconds} catch (interruptedexception E) {e.printstacktrace();} System. out. Println ("window" + thread. Currentthread() Getname() + "one ticket sold," + "number of remaining tickets =" + (-- ticketnum));}@ Override public void run() {while (loop) {sell(); / / the sell method is a synchronization method}}}} public static void main (string [] args) {sellticket sellticket = new sellticket(); new thread (sellticket). Start(); / / window 1 new thread (sellticket). Start(); / / window 2 new thread (sellticket). Start() ;// Window 3}
mutex
-
Basic introduction
- In the Java language, the concept of object mutex is introduced to ensure the integrity of shared data operations.
- Each object corresponds to a tag called "mutex", which is used to ensure that only one thread can access the object at any time
- Keyword synchronized to associate with the mutex of the object. When an object is decorated with synchronized, it indicates that the object can only be accessed by one thread at any time
- Limitation of synchronization: the execution efficiency of the program should be reduced
- The lock of the synchronization method (non static) can be this or other objects (the same object is required)
- The lock of the synchronous method (static) is the current class itself
-
Precautions and details
- If the synchronization method is not decorated with static, the default lock object is this
- If the method is decorated with static, the default lock object is the current class class
- Landing steps:
- You need to analyze the locked code first
- Select a synchronization code block or synchronization method
- It is required that the lock object of multiple threads be the same!
//Implement the interface method. Use synchronized to synchronize threads. Class sellticket implements runnable {private static int ticketnum = 100; / / let multiple threads share private boolean loop=true; / / control the run method variable object object = new object(); / / 1. Public synchronized static void m1() {} the lock is added to sellticket class //2. If you are in static, implement a synchronized code block public static void m1() {synchronized (sellticket. Class) {}} / / 1 Public synchronized void sell() {} is a synchronization method / / 2 At this time, it is locked in this object / / 3 You can also write synchronized on the code block to synchronize the code block, The mutex is still in the public void sell() {/ / synchronization method of this object. At the same time, only one thread can execute the sell method synchronized (/ * this * / object) {if (ticketnum < = 0) {system.out.println ("ticket end"); loop = false; return;} Try {thread. Sleep (50); / / sleep for 50 milliseconds} catch (interruptedexception E) {e.printstacktrace();} System. out. Println ("window" + thread. Currentthread() Getname() + "one ticket sold," + "number of remaining tickets =" + (-- ticketNum));}}
Thread deadlock
- Basic introduction
Multiple threads occupy each other's lock resources, but they don't want to, resulting in deadlock. In programming, we must avoid deadlock.
class SellTicket extends Thread{ static Object o1=new Object(); static Object o2=new Object(); boolean flag; public SellTicket(boolean flag) { this.flag = flag; } @Override public void run() { //1. If the flag is t, thread A will get / hold the o1 object lock first, and then try to get the o2 object lock / / 2 If thread A cannot get o2 object lock, it will be blocked / / 3 If the flag is f, thread B will first get / hold the o2 object lock, and then try to get the o1 object lock / / 4 If thread B cannot get the o1 object lock, Blocked if (flag) {synchronized (o1) {/ / object mutex. The following is the synchronization code System.out.println(Thread.currentThread().getName() + "enter 1"); synchronized (o2) {/ / here you get the monitoring right of li object System.out.println(Thread.currentThread().getName() + "enter 2" ); } } } Else {synchronized (o2) {System.out.println(Thread.currentThread().getName() + "enter 3"); synchronized (o1) {/ / here you get the monitoring right of the li object System.out.println(Thread.currentThread().getName() + "enter 4");}}}}}}} Public static void main (string [] args) {/ / simulate deadlock object sellticket A = new sellticket (true); A.setname ("A thread"); sellticket B = new sellticket (false); b.setname ("B thread"); A.start(); b.start();}
Release lock
-
The following operation will release the lock
- The execution of the synchronization method and synchronization code block of the current thread ends
Case: go to the bathroom and come out when you're done
- The current thread encounters break and return in the synchronization code block and synchronization method
Case: without normal completion, the manager asked him to modify the bug and had to come out
- The current thread has an unhandled error or exception in the synchronization code block and synchronization method, resulting in an abnormal end
Case: without normal completion, if you find that you have forgotten to bring paper, you can't come out
- The wait() method of the thread object is executed in the synchronization code block and synchronization method of the current thread. The current thread pauses and releases the lock
Case: there is no normal completion. I think it needs brewing, so I will go in later
-
The following operation will not release the lock
- When a thread executes a synchronization method or a synchronization code block, the program calls thread sleep(),Thread. The yield () method pauses the execution of the current thread and does not release the lock
Case: I was too sleepy when I went to the bathroom. I narrowed in the pit for a while
- When a thread executes a synchronous code block, other threads call the thread's suspend() method to suspend the thread, and the thread will not release the lock
Tip: you should try to avoid using suspend() and resume() to control threads. This method is no longer recommended