Process and thread
concept
Process: a process is an execution process of a program. It is the basic unit for allocating and managing resources during program execution. Each process has its own memory space.
Thread: thread is the basic unit of CPU resource scheduling and allocation. It can share process resources with other threads in the same process.
contact
A thread is a part of a process. A process can have multiple threads, but a thread can only exist in one process.
difference
Fundamental difference: process is the basic unit of operating system resource scheduling, and thread is the basic unit of execution scheduling.
Overhead: the process switching overhead is large, and the thread switching overhead is small.
Sharing: a process has its own independent address space and resources, and threads share the resources of its own process.
Implementation of Java multithreading
Inherit Thread class
package com.Thread.create; //Inherit the Thread class and override the run() method class MyThread extends Thread{ @Override public void run() { for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName() + ":" + i); } } } public class ThreadDemo_one { public static void main(String[] args) { //Create a thread and execute Thread my_thread = new MyThread(); my_thread.start(); //Execution of main thread for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+ ":" + i); } } }
Implement Runnable interface
package com.Thread.create; //Implement the Runnable interface and rewrite the run() method class My_Runnable implements Runnable{ @Override public void run() { for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName() + ":" + i); } } } public class ThreadDemo_two { public static void main(String[] args) { //Create a thread and execute //1. Create Runnable object My_Runnable me = new My_Runnable(); //2. Pass the Runnable object to the Thread class Thread t = new Thread(me); //3. Open thread t.start(); //Execution of main thread for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+ ":" + i); } } }
Implement Callable interface
package com.Thread.create; //Implement the Callable interface and override the call() method import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; class My_Callable implements Callable{ @Override public Object call() throws Exception { for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName() + ":" + i); } return null; } } public class ThreadDemo_three { public static void main(String[] args) { //Create a thread and execute //Create Callable object Callable my_callable = new My_Callable(); //Wrap the Callable object with the FutureTask class FutureTask my_task = new FutureTask(my_callable); //Pass FutureTask to the Thread class Thread t = new Thread(my_task); t.start(); //Execution of main thread for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+ ":" + i); } } }
Use thread pool
package com.Thread.create; //Use thread pool import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class My_runnable implements Runnable{ @Override public void run() { for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName() + ":" + i); } } } public class ThreadDemp_four { public static void main(String[] args) { //Create thread pool ExecutorService executorService = Executors.newFixedThreadPool(5); //Create Runnable object Runnable me = new My_runnable(); //Get the thread object from the thread pool and pass the Runnable object executorService.submit(me); //Close the thread pool. The production environment is irrelevant executorService.shutdown(); //Execution of main thread for (int i=0;i<100;i++){ System.out.println(Thread.currentThread().getName()+ ":" + i); } } }
Comparison of advantages and disadvantages of four creation methods
Advantages of implementing Runnable interface over inheriting Thread class:
1. It avoids the limitation of Java single inheritance
2. It is suitable for multiple same program codes to share the same resource
3. Only threads that implement Runnable or Callable classes can be placed in the Thread pool, not inherited Thread classes
Compared with Runnable, Callable:
The main difference is that the call() method has a return value, while the run() method does not
Benefits of using thread pools:
1. Improve response speed and reduce thread creation time
2. Reduce resource consumption and reuse threads in the thread pool
3. It is convenient for thread management. The number of work line threads in the thread pool can be adjusted according to the bearing capacity of the system to prevent the server from getting tired due to excessive memory consumption
Thread synchronization (thread safety)
Thread safety
The so-called thread safety is that multiple threads run at the same time, and these threads may run this piece of code at the same time. Each time the program runs, the result is the same as that of a single thread, and the value of the variable is the same as expected.
Thread safety problems occur when multiple threads access shared resources
Thread synchronization
The use of synchronized mechanism can solve the thread safety problem of multiple threads accessing the same resource
The following ticket buying classes are thread unsafe classes
package com.Thread.synchronize; public class Sell_Ticket implements Runnable{ int ticket = 100; @Override public void run() { while (true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if(ticket>0){ System.out.println(Thread.currentThread().getName()+"-->Selling the third"+ticket+"Ticket"); ticket--; } } } }
Synchronous code block
synchronized(Synchronous lock){ Code that requires synchronization } Synchronous lock: 1,Can be any object 2,Multiple thread objects need to use the same lock
package com.Thread.synchronize; //Using synchronous code blocks to realize thread safety /* synchronized(Synchronous lock){ Code that requires synchronization } Synchronous lock: 1,Can be any object 2,Multiple thread objects need to use the same lock */ public class Sell_Ticket_Synchronized_one implements Runnable{ private int ticket = 100; //Create a lock object Object obj = new Object(); @Override public void run() { while (true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (obj){ if(ticket>0){ System.out.println(Thread.currentThread().getName()+"-->Selling the third"+ticket+"Ticket"); ticket--; } } } } }
Synchronization method
public synchronized void method(){ Code that may cause thread safety problems } Who is the sync lock? For non static method,Synchronous lock is this. about static method,We use the bytecode object of the class where the current method is located(Class name.class).
package com.Thread.synchronize; //Using synchronization method to realize thread safety /* The lock object of the synchronization method is its own this */ public class Sell_Ticket_Synchronized_two implements Runnable{ private int ticket = 100; @Override public void run() { while (true){ sell_ticket(); } } private synchronized void sell_ticket(){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if(ticket>0){ System.out.println(Thread.currentThread().getName()+"-->Is selling"+ticket+"Ticket"); ticket--; } } }
Lock lock
java.util.concurrent.locks.Lock The mechanism provides better performance than synchronized Code blocks and synchronized Method for a wider range of locking operations,Synchronous code block/Functions of synchronization method Lock Both,In addition, it is more powerful,More object-oriented. Lock Lock is also called synchronous lock. The locking and releasing methods are as follows: public void lock() :Add synchronous lock. public void unlock() :Release the synchronization lock.
package com.Thread.synchronize; //Using lock object to realize thread safety import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Sell_Ticket_Synchronized_three implements Runnable{ private int ticket = 100; //Create lock object Lock lock = new ReentrantLock(); @Override public void run() { while (true){ //Lock lock.lock(); try { Thread.sleep(10); if(ticket>0){ System.out.println(Thread.currentThread().getName()+"-->Selling the third"+ticket+"Ticket"); ticket--; } } catch (InterruptedException e) { e.printStackTrace(); }finally { //Release lock lock.unlock(); } } } }
Thread communication (producer and consumer)
Thread communication
concept
Multiple threads are processing the same resource, but the processing actions (tasks of threads) are different.
For example, thread A is used to generate steamed stuffed buns and thread B is used to eat steamed stuffed buns. Steamed stuffed buns can be understood as the same resource. The actions processed by thread A and thread B are production and consumption, so there is A thread communication problem between thread A and thread B.
Why handle thread communication
When multiple threads execute concurrently, by default, the CPU switches threads randomly. When we need multiple threads to complete a task together, and we want them to execute regularly, some coordinated communication is needed between multiple threads to help us operate a piece of data together.
To sum up, we want threads to execute regularly
How to communicate
Use the wake-up waiting mechanism
Wait for wake-up mechanism
What is waiting to wake up
This is a collaboration mechanism between multiple threads. When it comes to threads, we often think of the race between threads, such as competing for locks, but this is not the whole story. There will also be a cooperation mechanism between threads. Just like you and your colleagues in the company, you may have competition for promotion, but more often you work together to complete certain tasks.
That is, after a thread has performed the specified operation, it enters the waiting state (wait()) and wakes up after other threads have executed their specified code (notify()); When there are multiple threads waiting, you can use notifyAll() to wake up all waiting threads if necessary.
wait/notify is a cooperative mechanism between threads.
Method of waiting for wake-up
1. Wait: the thread is no longer active, no longer participates in scheduling, and enters the wait set. Therefore, CPU resources will not be wasted, nor will it compete for locks. At this time, the thread state is WAITING. It also waits for other threads to perform a special action, that is, to "notify" the threads WAITING on this object to be released from the wait set and re-enter the ready queue
2. notify: select a thread in the wait set of the notified object to release; For example, when a restaurant has a free seat, the customer waiting for the longest meal takes the first seat.
3. notifyAll: release all threads on the wait set of the notified object.
Details of calling wait and notify methods
1. The wait method and notify method must be called by the same lock object. Because: the corresponding lock object can wake up the thread after using the wait method called by the same lock object through notify.
2. The wait method and notify method are methods belonging to the Object class. Because: the lock Object can be any Object, and the class of any Object inherits the Object class.
3. The wait method and notify method must be used in the synchronization code block or synchronization function. Because: these two methods must be called through the lock object.
Producer consumer model
The waiting wake-up mechanism is actually a classic problem of "producers and consumers".
Take the production of steamed stuffed buns and the consumption of steamed stuffed buns as an example. How can the waiting wake-up mechanism make effective use of resources
Baozi shop thread produces baozi, and eating thread consumes baozi. When there is no steamed stuffed bun (the status of steamed stuffed bun is false),The eating thread waits, and the baozi shop thread produces baozi (that is, the baozi status is true),And notify the eating thread (release the waiting state of eating),Because there are already steamed stuffed buns, the steamed stuffed buns shop thread enters the waiting state. Next, whether the eating thread can further execute depends on the acquisition of the lock. If the lock is obtained, the action of eating steamed stuffed buns is executed, and the steamed stuffed buns are finished (the status of steamed stuffed buns is false),And notify the thread of the package store (release the waiting state of the package store),The eating thread is waiting. Whether the package shop thread can execute further depends on the acquisition of the lock.
code implementation
Steamed stuffed bun
package com.Thread.communication; //Steamed stuffed bun, also known as resource class public class BaoZi { //Steamed stuffed bun skin String pi; //Steamed stuffed bun stuffing String xian; //The status of the package, indicating whether the resource exists boolean flag = false; }
Class for producing steamed stuffed bun
package com.Thread.communication; //A steamed stuffed bun shop means a producer who produces steamed stuffed buns public class BaoZi_Producer extends Thread{ private BaoZi baozi; public BaoZi_Producer(BaoZi baozi){ this.baozi = baozi; } @Override public void run() { int count = 0; //Keep producing and use the while(true) loop while (true){ synchronized (baozi){ if (baozi.flag == true){ try { baozi.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //Increase interest if (count%2==0){ baozi.pi = "Thin skin"; baozi.xian = "Beef stuffing"; System.out.println("Steamed buns shop produces steamed buns-->"+baozi.pi+baozi.xian+"steamed stuffed bun"); }else{ baozi.pi = "Crispy"; baozi.xian = "Pork stuffing"; System.out.println("Steamed buns shop produces steamed buns-->"+baozi.pi+baozi.xian+"steamed stuffed bun"); } //It takes five seconds to make a steamed stuffed bun try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } count++; baozi.flag = true; baozi.notify(); } } } }
Steamed stuffed bun eating class
package com.Thread.communication; //Steamed stuffed bun consumers public class BaoZi_Comsumer extends Thread{ private BaoZi baozi; public BaoZi_Comsumer(BaoZi baozi){ this.baozi = baozi; } @Override public void run() { while (true){ synchronized (baozi){ if (baozi.flag==false){ try { baozi.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Eat steamed stuffed bun-->"+baozi.pi+baozi.xian+"steamed stuffed bun"); //Eat steamed stuffed bun for 3 seconds try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } baozi.flag = false; baozi.notify(); System.out.println("----------------------------------"); } } } }
Test class
package com.Thread.communication; public class Test { public static void main(String[] args) { BaoZi baozi = new BaoZi(); BaoZi_Producer bp = new BaoZi_Producer(baozi); BaoZi_Comsumer bc = new BaoZi_Comsumer(baozi); bp.start(); bc.start(); } }