1. Thread introduction
1.1 multithreading
Multitasking: playing mobile while eating
But in essence, the brain still does only one thing at a time
1.2 program, process and thread
The program is static, and the process is the process of program execution. A process can have multiple threads, and the real execution is threads
2. Three ways to create threads
2.1 inherit Thread class
//Thread creation method 1: inherit the thread class, rewrite the run() method, and call start to start the thread public class TestThread1 extends Thread{ @Override public void run() { //run method thread body for (int i = 0; i <20 ; i++) { System.out.println("I'm looking at the code"); } } public static void main(String[] args) { //main thread //Create a thread object TestThread1 testThread1=new TestThread1(); //Call the start() method to start the thread testThread1.start(); for (int i = 0; i < 2000; i++) { System.out.println("I'm learning multithreading"); } } }
Summary:
- Thread startup is not necessarily executed immediately, but is scheduled by the CPU
- Thread creation method 1: inherit the thread class, rewrite the run() method, and call start to start the thread
2.2 example: network diagram Download
import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; //Practice Thread to realize multi-threaded synchronous downloading of pictures public class TestThread2 extends Thread{ private String url;//Network picture address private String name;//Saved file name public TestThread2(String url ,String name){ this.url=url; this.name=name; } //The execution body of the download image thread @Override public void run() { WebDownloader webDownloader=new WebDownloader(); webDownloader.downloade(url,name); System.out.println("Downloaded a file named:"+name); } public static void main(String[] args){ TestThread2 t1=new TestThread2("https://www.51wendang.com/doc/c4ea862180e68ca5a074899dfd85634723c2e5ec/10","2.jpg"); t1.start(); } } //Downloader class WebDownloader{ //Download method public void downloade(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO abnormal"); } } }
2.3 runnable interface
//Thread creation method 1: implement the runnable interface and rewrite the run() method. The execution thread needs to throw in the runnable interface implementation class and call the start method public class TestThread3 implements Runnable{ @Override public void run() { //run method thread body for (int i = 0; i <20 ; i++) { System.out.println("I'm looking at the code"+i); } } public static void main(String[] args) { //Create an implementation class object for the runnbale interface TestThread3 testThread3=new TestThread3(); //Create a thread object and start our thread proxy through the thread Thread thread=new Thread(testThread3); thread.start(); new Thread(testThread3).start(); for (int i = 0; i < 20; i++) { System.out.println("I'm learning multithreading"+i); } } }
Inherit Thread class
- Subclass inherits Thread class and has multithreading capability
- start thread: subclass object. start()
- Not recommended: avoid the limitation of OOP single inheritance
Implement Runnable interface
- The implementation interface Runnable has multithreading capability
- Start Thread: pass in the target object + Thread object. start()
- Recommended: it avoids the limitation of single inheritance, is flexible and convenient, and is convenient for the same object to be used by multiple threads
Multiple threads operate on the same object case
public class TestThread4 implements Runnable{ //Number of votes private int ticketNums=10; @Override public void run() { while(true){ if (ticketNums<=0){ break; } //Analog delay try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //Gets the name of the Thread System.out.println(Thread.currentThread().getName()+"Got the second"+ticketNums--+"ticket"); } } public static void main(){ TestThread4 testThread4=new TestThread4(); new Thread(testThread4,"Xiao Ming"); new Thread(testThread4,"teacher"); new Thread(testThread4,"cattle"); } }
2.4 tortoise rabbit race
//Simulated tortoise rabbit race public class Race implements Runnable{ //winner private static String winner; @Override public void run() { for (int i = 0; i <= 100; i++) { if (Thread.currentThread().getName().equals("rabbit") && i % 10 == 0) { try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } } boolean flag=gameOver(i); if(flag){ break; } System.out.println(Thread.currentThread().getName() + "-->Run away" + i + "step"); } } //Judge whether to complete the game private boolean gameOver(int steps){ //Judge whether there is a winner if (winner!=null){ return true; }{ if (steps==100){ winner=Thread.currentThread().getName(); System.out.println("winner is "+winner); return true; } } return false; } public static void main(String[] args) { Race race=new Race(); new Thread(race,"rabbit").start(); new Thread(race,"tortoise").start(); } }
(3) Callable interface (understand)
package Callable; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; public class TestCallable implements Callable<Boolean> { private String url;//Network picture address private String name;//Saved file name public TestCallable(String url ,String name){ this.url=url; this.name=name; } //The execution body of the download image thread @Override public Boolean call() { WebDownloader webDownloader=new WebDownloader(); webDownloader.downloader(url,name); System.out.println("Downloaded a file named:"+name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable t1=new TestCallable("https://www.51wendang.com/doc/c4ea862180e68ca5a074899dfd85634723c2e5ec/10","1.jpg"); TestCallable t2=new TestCallable("https://www.51wendang.com/doc/c4ea862180e68ca5a074899dfd85634723c2e5ec/10","2.jpg"); TestCallable t3=new TestCallable("https://www.51wendang.com/doc/c4ea862180e68ca5a074899dfd85634723c2e5ec/10","3.jpg"); //Create execution service: ExecutorService ser = Executors.newFixedThreadPool(3); //Submit for execution Future<Boolean> r1=ser.submit(t1); Future<Boolean> r2=ser.submit(t2); Future<Boolean> r3=ser.submit(t3); //Get results boolean rs1=r1.get(); boolean rs2=r2.get(); boolean rs3=r3.get(); //Shut down service ser.shutdownNow(); } } //Downloader class WebDownloader{ //Download method public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO abnormal"); } } }
Callable benefits:
- You can define the return value
- Exceptions can be thrown
3.Thread class proxy object
Summary of static proxy mode:
- Both real roles and proxy objects need to implement the same interface
- The proxy object is to proxy the real role
Benefits:
- Proxy objects can do many things that real objects can't do
- Real objects focus on doing their own things
public class StacticProxy { public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { System.out.println("123"); } }).start(); new WeddingCompany(new You()).HappyMarry(); new WeddingCompany(new You()); WeddingCompany weddingCompany=new WeddingCompany(new You()); weddingCompany.HappyMarry(); } } interface Marry{ void HappyMarry(); } //Real character, you get married class You implements Marry{ @Override public void HappyMarry() { System.out.println("Teacher Qin married"); } } //Acting role to help you get married class WeddingCompany implements Marry{ private Marry target; public WeddingCompany(Marry target) { this.target = target; } @Override public void HappyMarry() { before(); this.target.HappyMarry(); after(); } private void after() { System.out.println("After marriage"); } private void before() { System.out.println("Before marriage"); } }
4.Lamda expression
4.1 why use lambda expressions?
- Avoid too many anonymous inner class definitions
- It can make your code look more concise
- Removed a pile of meaningless code, leaving only the core logic
Definition of functional interface
- Any interface that contains only one abstract method is a functional interface
- For functional interfaces, you can create objects of the interface through Lambda expressions
public class lamdba { //3. Static internal class static class Like2 implements ILike{ @Override public void lambda() { System.out.println("i like lambda2"); } } public static void main(String[] args) { ILike like=new Like(); like.lambda(); like=new Like2(); like.lambda(); //4. Local internal class class Like3 implements ILike{ @Override public void lambda() { System.out.println("i like lambda3"); } } like=new Like3(); like.lambda(); //5. Anonymous internal class. There is no class name. You must use the interface or parent class. Pay attention to the semicolon like=new ILike(){ @Override public void lambda() { System.out.println("i like lambda4"); } }; like.lambda(); //6. Simplify with Lambda like=()->{ System.out.println("i like lambda5"); }; like.lambda(); } } //1. Define a functional interface interface ILike{ void lambda(); } //2. Implementation class class Like implements ILike{ @Override public void lambda() { System.out.println("i like lambda1"); } }
- External classes are placed inside to become static internal classes, and static needs to be added
- Static methods can only use static members
- main is static and cannot access non static methods and variables in a class
- Local inner classes are placed directly in methods
lambda simplification
ILove love=null; //1.lambda simplification love=(int a)->{ System.out.println("i love you-->"+a); } //Simplified parameter type love=(a)->{ System.out.println("i love you-->"+a); } //Simplified parentheses love=a->{ System.out.println("i love you-->"+a); } //Simplified curly braces love=a->System.out.println("i love you-->"+a); love.love(521);
Summary:
- lambda expressions can be reduced to one line only if there is one line of code. If there are multiple lines, they are wrapped in code blocks
- The premise is that the interface is functional
- You can also remove parameter types from multiple parameters. If you want to remove them, you can remove them all,
5. Thread status
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-XOV919Ln-1636557470627)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211109150003879.png)]
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-PxiJTi9e-1636557470628)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211109150143641.png)]
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-9XFBcUJX-1636557470630)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211109150334204.png)]
5.1 thread stop
//Test stop //1. It is recommended that the thread stop normally -- > utilization times, and dead loop is not recommended //2. It is recommended to use flag bit -- > to set a flag bit //3. Do not use outdated methods such as stop or destroy or methods not recommended by JDK public class TestStop implements Runnable{ //1. Set a flag bit private boolean flag=true; @Override public void run() { int i=0; while(flag){ System.out.println("run......ing"+i++); } } //2. Set a public method to stop the thread and convert the flag bit public void stop(){ this.flag=false; } public static void main(String[] args) { TestStop testStop=new TestStop(); new Thread(testStop).start(); for (int i = 0; i < 1000; i++) { System.out.println("main"+i); if (i==900){ //Call the stop method to switch the flag bit and stop the thread testStop.stop(); System.out.println("The thread should stop"); } } } }
be careful:
- It is recommended that the thread stop normally – > utilization times, and dead loop is not recommended
- It is recommended to use flag bit – > to set a flag bit
- Do not use outdated methods such as stop or destroy, or methods that are not recommended by JDK
5.2 thread hibernation
//Analog network delay: the occurrence of amplification problems public class TestSleep implements Runnable{ //Number of votes private int ticketNums=10; @Override public void run() { while(true){ if (ticketNums<=0){ break; } //Analog delay try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //Gets the name of the Thread System.out.println(Thread.currentThread().getName()+"Got the second"+ticketNums--+"ticket"); } } public static void main(String[] args) { TestSleep testThread4=new TestSleep(); new Thread(testThread4,"Xiao Ming").start(); new Thread(testThread4,"teacher").start(); new Thread(testThread4,"cattle").start(); } }
import java.text.SimpleDateFormat; import java.util.Date; public class TestSleep2 { public static void main(String[] args) { //count down try { tenDown(); } catch (InterruptedException e) { e.printStackTrace(); } //Print current system time Date startTime=new Date(System.currentTimeMillis());//get SysTime while(true){ try { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime)); startTime=new Date(System.currentTimeMillis());//Update current time } catch (InterruptedException e) { e.printStackTrace(); } } } //Analog countdown public static void tenDown() throws InterruptedException { int num=10; while(true){ Thread.sleep(1000); System.out.println(num--); if (num<=0){ break; } } } }
be careful:
- sleep specifies the number of milliseconds the current thread is blocking
- Exception InterruptedException in sleep
- When the sleep time reaches, the thread enters the ready state
- sleep can simulate network delay, countdown, etc
- Each object has a lock, and sleep does not release the lock
5.3 comity
//Test comity thread //Comity does not necessarily succeed. It depends on your mood public class TestYied { public static void main(String[] args) { MyYield myYield=new MyYield(); new Thread(myYield,"a").start(); new Thread(myYield,"b").start(); } } class MyYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"Thread starts execution"); Thread.yield();//Thread comity System.out.println(Thread.currentThread().getName()+"Thread stop execution"); } }
be careful:
- Comity thread, which suspends the currently executing thread without blocking
- Transition a thread from a running state to a ready state
- Let the CPU reschedule, comity is not necessarily successful! Look at CPU mood
5.4 thread enforcement
public class TestJoin implements Runnable{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("thread vip coming"+i); } } public static void main(String[] args) throws InterruptedException { //Start our thread TestJoin testJoin=new TestJoin(); Thread thread=new Thread(testJoin); thread.start(); //Main thread for (int i = 0; i < 1000; i++) { if (i==200){ thread.join();//Jump in line } System.out.println("main"+i); } } }
6. Thread state observation
public class TestSate { public static void main(String[] args) throws InterruptedException { Thread thread=new Thread(()->{ for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); //Observation state Thread.State state=thread.getState(); System.out.println(state); //Observe after startup thread.start();//Start thread state=thread.getState(); System.out.println(state);//Run while(state!=Thread.State.TERMINATED){//As long as the thread does not terminate, it always outputs the state Thread.sleep(100); state=thread.getState();//Update thread status System.out.println(state); } } }
7. Thread priority
//Test thread priority public class TestPriority { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); MyPriority myPriority=new MyPriority(); Thread t1=new Thread(myPriority); Thread t2=new Thread(myPriority); Thread t3=new Thread(myPriority); Thread t4=new Thread(myPriority); Thread t5=new Thread(myPriority); //Set priority before starting t1.start(); t2.setPriority(1); t2.start(); t3.setPriority(4); t3.start(); t4.setPriority(Thread.MAX_PRIORITY); t4.start(); t5.setPriority(1); t5.start(); } } class MyPriority implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); } }
Summary:
-
java provides a thread scheduler to monitor all threads in the ready state after startup. The thread scheduler determines which thread should be scheduled to execute according to priority
-
The priority of threads is expressed mathematically, ranging from 1 to 10
- Thread.MIN_PRIOITY=1;
- Thread.MAX_PRIORITY=10;
- Thread.NORM_PRIORITY=5;
-
Change or get priority in the following ways
- getPriority
- setPriority(int XXX)
-
Priority should be set before start() scheduling
-
Low priority only means that the probability of obtaining scheduling is low, not that it will not be called if the priority is low. This depends on the CPU scheduling (performance inversion)
8. Daemon thread
//Test daemon thread //God protects you public class TestDamon { public static void main(String[] args) { God god=new God(); Youe you=new Youe(); Thread thread=new Thread(god); thread.setDaemon(true);//The default is false, which means that it is a user thread. Normal threads are user threads thread.start();//God daemon thread start new Thread(you).start(); } } //lord class God implements Runnable{ @Override public void run() { while (true){ System.out.println("God bless you"); } } } //you class Youe implements Runnable{ @Override public void run() { for (int i = 0; i < 36500; i++) { System.out.println("You live happily all your life"); } } }
be careful:
- Threads are divided into user threads and daemon threads
- The virtual machine must ensure that the user thread has completed execution
- The virtual machine does not have to wait for the daemon thread to finish executing
- Such as: recording operation logs in the background, monitoring memory, garbage collection and so on
9. Thread synchronization
Multiple threads operate on the same resource
Concurrency: the same object is operated by multiple threads at the same time
When dealing with multithreading, multiple threads access the same object, and some threads also want to modify the object. At this time, we need thread synchronization. Thread synchronization is actually a waiting mechanism. Multiple threads that need to access this object at the same time enter the waiting pool of this object to form a queue, wait for the previous thread to be used, and then use the next thread
Forming condition: queue + lock
Locking mechanism: synchronized
Because multiple threads of the same process share the same storage space, it brings convenience and access conflict. In order to ensure the correctness of data access in the method, the lock mechanism synchronized is added during access. When one thread obtains the exclusive lock of the object and monopolizes resources, other threads must wait and release the lock after use.
The following problems exist:
- Holding a lock by one thread will cause all other threads that need the lock to hang
- In multi-threaded competition, locking and releasing locks will lead to more context switching and scheduling delays, resulting in performance problems
- If a high priority thread waits for a low priority thread to release the lock, it will lead to priority inversion and performance problems.
10. Three cases of insecurity
//Unsafe ticket buying //Thread unsafe public class UnsafeBuy { public static void main(String[] args) { BuyTicket station=new BuyTicket(); new Thread(station,"Xiao Ming").start(); new Thread(station,"I").start(); new Thread(station,"Qin Dynasty").start(); } } class BuyTicket implements Runnable{ //ticket private int ticketNums=10; boolean flag=true;//External stop mode @Override public void run() { //Buy a ticket while (flag){ buy(); } } private void buy(){ //Judge whether there are tickets if(ticketNums<=0){ flag=false; return; } //Analog delay try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Buy a ticket System.out.println(Thread.currentThread().getName()+"Get"+ticketNums--); } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-HPlOwnyi-1636557470632)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110184917492.png)]
Someone gets 0, - 1. The thread is not safe
//Unsafe withdrawal //Two people go to the bank to withdraw money and open an account public class UnsafeBank { public static void main(String[] args) { //account Account account=new Account(100,"Marriage fund"); Drawing you=new Drawing(account,50,"you"); Drawing girlFrend=new Drawing(account,100,"girlFrend"); you.start(); girlFrend.start(); } } //account class Account{ int money;//balance String name;//Card name public Account(int money,String name){ this.money=money; this.name=name; } } //Bank: simulated withdrawal class Drawing extends Thread{ Account account;//account //How much did you withdraw int drawingMoney; //How much money do you have now int nowMoney; public Drawing(Account account,int drawingMoney,String name){ super(name); this.account=account; this.drawingMoney=drawingMoney; } //Withdraw money @Override public void run() { //Judge whether there is money if(account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"There's not enough money to withdraw"); return; } //sleep can amplify the occurrence of problems try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Card balance = balance - you get money account.money=account.money-drawingMoney; //The money in your hand nowMoney =nowMoney+drawingMoney; System.out.println(account.name+"The balance is:"+account.money); //Thread.currentThread().getName()=this.getName() System.out.println(this.getName()+"Money in hand:"+nowMoney); } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (IMG siyroxzr-1636557470634) (E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110185053642.png)]
import java.util.ArrayList; import java.util.List; //Thread unsafe collection public class UnsafeList { public static void main(String[] args) { List<String> list =new ArrayList<String>(); // for (int i = 0; i < 10000; i++) { // new Thread(()->{ // list.add(Thread.currentThread().getName()); // }).start();; // } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
11. Synchronization method and synchronization block
Synchronization method:
- Because we can use the private keyword to ensure that data objects can only be accessed by methods, we only need to propose a mechanism for methods. This mechanism is the synchronized keyword, which includes two uses: the synchronized method and the synchronized block.
- Synchronization method: public synchronized void method(int args) {}
- The synchronized method controls access to "objects", and each object corresponds to a lock. Each synchronized method must obtain the lock of the object calling the method before it can be executed. Otherwise, the thread will block. Once the method is executed, it will monopolize the lock and release the lock until the method returns. Only later blocked threads can obtain the lock and continue to execute.
- Defect: declaring a large method synchronized will affect efficiency
Synchronization block:
- Synchronization block: synchronized(obj) {}
- Obj calls it a synchronization monitor
- Obj can be any object, but it is recommended to use shared resources as synchronization monitors
- There is no need to specify a synchronization monitor in the synchronization method, because the synchronization monitor of the synchronization method is this, the object itself, or class [explained in reflection]
- Synchronization monitor execution
- The first thread accesses, locks the synchronization monitor, and executes the code in it
- The second thread accesses and finds that the synchronization monitor is locked and cannot be accessed
- After the first thread is accessed, unlock the synchronization monitor
- The second thread accesses, finds that the synchronization monitor has no lock, and then locks and accesses
Problem solving:
Add synchronized before the method
//Unsafe ticket buying //Thread unsafe public class UnsafeBuy { public static void main(String[] args) { BuyTicket station=new BuyTicket(); new Thread(station,"Xiao Ming").start(); new Thread(station,"I").start(); new Thread(station,"Qin Dynasty").start(); } } class BuyTicket implements Runnable{ //ticket private int ticketNums=10; boolean flag=true;//External stop mode @Override public void run() { //Buy a ticket while (flag){ buy(); } } //The synchronized synchronization method locks this private synchronized void buy(){ //Judge whether there are tickets if(ticketNums<=0){ flag=false; return; } //Analog delay try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Buy a ticket System.out.println(Thread.currentThread().getName()+"Get"+ticketNums--); } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-KwNV4aFF-1636557470635)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110200812079.png)]
synchronized the default lock is this, and the object of the lock is the amount of change
//Unsafe withdrawal //Two people go to the bank to withdraw money and open an account public class UnsafeBank { public static void main(String[] args) { //account Account account=new Account(100,"Marriage fund"); Drawing you=new Drawing(account,50,"you"); Drawing girlFrend=new Drawing(account,100,"girlFrend"); you.start(); girlFrend.start(); } } //account class Account{ int money;//balance String name;//Card name public Account(int money,String name){ this.money=money; this.name=name; } } //Bank: simulated withdrawal class Drawing extends Thread{ Account account;//account //How much did you withdraw int drawingMoney; //How much money do you have now int nowMoney; public Drawing(Account account,int drawingMoney,String name){ super(name); this.account=account; this.drawingMoney=drawingMoney; } //Withdraw money //synchronized the default lock is this @Override public void run() { synchronized (account){ //Judge whether there is money if(account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"There's not enough money to withdraw"); return; } //sleep can amplify the occurrence of problems try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Card balance = balance - you get money account.money=account.money-drawingMoney; //The money in your hand nowMoney =nowMoney+drawingMoney; System.out.println(account.name+"The balance is:"+account.money); //Thread.currentThread().getName()=this.getName() System.out.println(this.getName()+"Money in hand:"+nowMoney); } } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-apg3rGn3-1636557470637)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110201347348.png)]
12. Deadlock
//Deadlock: multiple threads hold each other's required resources to form a deadlock public class DeadLock { public static void main(String[] args) { Makeup g1=new Makeup(0,"Review noodle restaurant"); Makeup g2=new Makeup(1,"Snow White"); g1.start(); g2.start(); } } //Lipstick class Lipstick{ } //mirror class Mirror{ } class Makeup extends Thread{ //There is only one resource needed. Use static to ensure that there is only one static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); int choice;//choice String girlName;//People who use cosmetics Makeup(int choice,String girlName){ this.choice=choice; this.girlName=girlName; } @Override public void run() { //Make up try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } } //Make up, hold each other's locks, and need to get each other's resources private void makeup() throws InterruptedException { if(choice==0){ synchronized (lipstick){//Get lipstick lock System.out.println(this.girlName+"Get lipstick lock"); Thread.sleep(1000); synchronized (mirror){//Want to get a mirror in a second System.out.println(this.girlName+"Get the lock of the mirror"); } } }else{ synchronized (mirror){//Get the lock of the mirror System.out.println(this.girlName+"Get the lock of the mirror"); Thread.sleep(1000); synchronized (lipstick){//I want lipstick in a second System.out.println(this.girlName+"Get lipstick lock"); } } } } }
[the external chain image transfer fails, and the source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-rdQ4TlKm-1636557470638)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110204429224.png)], resulting in a deadlock
//Deadlock: multiple threads hold each other's required resources to form a deadlock public class DeadLock { public static void main(String[] args) { Makeup g1=new Makeup(0,"Review noodle restaurant"); Makeup g2=new Makeup(1,"Snow White"); g1.start(); g2.start(); } } //Lipstick class Lipstick{ } //mirror class Mirror{ } class Makeup extends Thread{ //There is only one resource needed. Use static to ensure that there is only one static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); int choice;//choice String girlName;//People who use cosmetics Makeup(int choice,String girlName){ this.choice=choice; this.girlName=girlName; } @Override public void run() { //Make up try { makeup(); } catch (InterruptedException e) { e.printStackTrace(); } } //Make up, hold each other's locks, and need to get each other's resources private void makeup() throws InterruptedException { if(choice==0){ synchronized (lipstick){//Get lipstick lock System.out.println(this.girlName+"Get lipstick lock"); Thread.sleep(1000); } synchronized (mirror){//Want to get a mirror in a second System.out.println(this.girlName+"Get the lock of the mirror"); } }else{ synchronized (mirror){//Get the lock of the mirror System.out.println(this.girlName+"Get the lock of the mirror"); Thread.sleep(2000); } synchronized (lipstick){//I want lipstick in a second System.out.println(this.girlName+"Get lipstick lock"); } } } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-WCb2ku2l-1636557470639)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110204357162.png)]
Four necessary conditions for deadlock generation:
- Mutex condition: a resource can only be used by one process at a time.
- Request and hold condition: when a process is blocked by requesting resources, it will hold on to the obtained resources.
- Conditions of non deprivation: the resources obtained by the process cannot be forcibly deprived until they are used up at the end of the year.
- Circular waiting condition: a circular waiting resource relationship is formed between several processes.
Note: as long as you find a way to break one or more of them, you can avoid deadlock
13. Lock
- Since JDK 5.0, Java has provided a more powerful thread synchronization mechanism -- synchronization is achieved by explicitly defining synchronization Lock objects. Synchronous locks use Lock objects as.
- The java.util.concurrent.locks.Lock interface is a tool that controls multiple threads to access shared resources. Locks provide exclusive access to shared resources. Only one thread can Lock the Lock object at a time. Threads should obtain the Lock object before accessing shared resources.
- ReentrantLock class implements Lock. It has the same concurrency and memory semantics as synchronized. ReentrantLock is commonly used in thread safety control, which can explicitly add and release locks.
ReentrantLock reentrant lock
//Test Lock public class TestLock { public static void main(String[] args) { TestLock2 testLock2=new TestLock2(); new Thread(testLock2).start(); new Thread(testLock2).start(); new Thread(testLock2).start(); } } //Test lock class TestLock2 implements Runnable{ int ticketNums=10; @Override public void run() { while(true){ if(ticketNums>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticketNums--); }else{ break; } } } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-JpLjRjKQ-1636557470640)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110210329899.png)]
import java.util.concurrent.locks.ReentrantLock; //Test Lock public class TestLock { public static void main(String[] args) { TestLock2 testLock2=new TestLock2(); new Thread(testLock2).start(); new Thread(testLock2).start(); new Thread(testLock2).start(); } } //Test lock class TestLock2 implements Runnable{ int ticketNums=10; //Define lock lock private final ReentrantLock lock=new ReentrantLock(); @Override public void run() { while(true){ try { lock.lock();//Lock if(ticketNums>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticketNums--); }else{ break; } }finally { //Unlock lock.unlock(); } } } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-o7n3MGuQ-1636557470641)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110210741397.png)] [the external chain image transfer fails. The source station may have an anti-theft mechanism. It is recommended to save the image and upload it directly (img-kwG4Srlr-1636557470642)(E: \ desktop \ document \ javaweb \ multithreading. assets\image-20211110210906842.png)]
14. Comparison between synchronized and Lock
- Lock is an explicit lock (manually open and close the lock, don't forget to close the lock). synchronized is an implicit lock, which is automatically released out of the scope
- Lock only has code block lock, and synchronized has code block lock and method lock
- Using Lock lock, the JVM will spend less time scheduling threads, have better performance, and have better scalability (provide more subclasses)
- Priority:
- Lock > synchronize code block (it has entered the method body and allocated corresponding resources) > synchronize method (outside the method body)
15. Thread collaboration
Producer consumer model
- Suppose only one product can be stored in the warehouse, the producer puts the produced products into the warehouse, and the consumer takes the products from the warehouse for consumption
- If there is no product in the warehouse, the producer will put the product into the warehouse, otherwise stop production and wait until the product in the warehouse is taken away by the consumer
- If there is a product in the warehouse, the consumer can take the product away for consumption, otherwise stop consumption and wait until the product is put in the warehouse again
This is a thread synchronization problem. Producers and consumers share the same resource, and producers and consumers are interdependent and conditional on each other
- For producers, they should inform consumers to wait before producing products, and after producing products, they need to inform consumers to consume immediately
- For consumers, after consumption, they should inform producers that they have finished consumption and need to produce new products for consumption
- In the producer consumer problem, synchronized is not enough
- synchronized prevents concurrent updates to the same shared resource, enabling synchronization
- synchronized cannot be used for message passing (Communication) between different threads
Therefore, Java provides several methods to solve the communication problem between threads
Method name | effect |
---|---|
wait() | It means that the thread waits until other threads notify it. Unlike sleep, it will release the lock |
wait(long timeout) | Specifies the number of milliseconds to wait |
notify() | Wake up a waiting thread |
nofityAll() | Wake up all threads calling the wait() method on the same object, and the threads with high priority are scheduled first |
Note: all methods of Object class can only be used in synchronization methods or synchronization code blocks, otherwise an exception IIIegalMoniTorStateException will be thrown
Concurrent collaboration model "producer / consumer model" - > management process method
- Producer: module responsible for production data (may be method, object, thread, process);
- Consumer: module responsible for processing data (may be method, object, thread, process);
- Buffer: consumers cannot directly use the producer's data. There is a "buffer" between them
//Test: producer consumer model -- > solution using cache: pipe process method //Producer, consumer, product, buffer public class TestPC { public static void main(String[] args) { SynContainer container=new SynContainer(); new Priductor(container).start(); new Consumer(container).start(); } } //producer class Priductor extends Thread{ SynContainer container; public Priductor(SynContainer container){ this.container=container; } //production @Override public void run() { for (int i = 0; i < 100; i++) { container.push(new Chicken(i)); System.out.println("production l"+i+"Chicken"); } } } //consumer class Consumer extends Thread{ SynContainer container; public Consumer(SynContainer container){ this.container=container; } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Consumer-->"+container.pop().id+"Chicken"); } } } //product class Chicken{ int id;//Product number public Chicken(int id) { this.id = id; } } //buffer class SynContainer{ //A container size is required Chicken[] chickens=new Chicken[10]; //Container counter int count=0; //The producer puts in the product public synchronized void push(Chicken chicken){ //If the container is full, it needs to wait for consumers to consume if (count==chickens.length){ //Inform consumers to consume and producers to wait } //If it is not full, we need to throw in the product chickens[count]=chicken; count++; //Consumers can be notified of consumption } //Consumer products public synchronized Chicken pop(){ //Judge whether it can be consumed if (count==0){ //Wait for producers to produce, consumers to wait } //If you can consume count--; Chicken chicken=chickens[count]; //When finished, inform the producer to produce return chicken; } }
The producer puts the produced data into the buffer, and the consumer takes out the data from the buffer
Signal lamp method
//Test producer consumer problem 2: signal lamp method, flag bit solution public class TestPc2 { public static void main(String[] args) { TV tv=new TV(); new Player(tv).start();; new Watcher(tv).start(); } } //Producer -- > actor class Player extends Thread{ TV tv; public Player(TV tv){ this.tv=tv; } @Override public void run() { for (int i = 0; i < 20; i++) { if (i%2==0){ this.tv.play("Happy base camp"); }else{ this.tv.play("Tiktok"); } } } } //Consumer -- > audience class Watcher extends Thread{ TV tv; public Watcher(TV tv){ this.tv=tv; } @Override public void run() { for (int i = 0; i < 20; i++) { this.tv.watch(); } } } //Products -- > Programs class TV{ //The actors performed and the audience waited //The audience watched and the actors waited String voice;//A performance boolean flag=true; //perform public synchronized void play(String voice){ if (!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("The actors performed:"+voice); //Inform the audience to watch this.notifyAll();//Notification wake up this.voice=voice; this.flag=!this.flag; } //watch public synchronized void watch(){ if (flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Watched:"+voice); //Inform the actors to perform this.notifyAll(); this.flag=!this.flag; } }
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-UDs4huSy-1636557470644)(E: \ desktop \ document \ javaweb \ multithreaded. assets\image-20211110222411684.png)]
16. Use thread pool
- Background: resources that are often created and destroyed and used heavily, such as threads in concurrency, have a great impact on performance.
- Idea: create several threads in advance, put them into the thread pool, get them directly when using them, and put them back into the pool after use. It can avoid frequent creation, destruction and reuse. It is similar to public transportation in life.
- benefit
- Improved response time (reduced time to create new threads)
- Reduce resource consumption (reuse threads in the thread pool and do not need to be created every time)
- Easy thread management (...)
- corePoolSize: size of the core pool maximumPoolSize: maximum number of threads
- keepAliveTime: when the thread has no task, how long will it last at most and then terminate
- JDK 5.0 provides APLS related to thread pool: executorservice and Executors
- ExecutorService: real thread pool interface. Common subclass ThreadPoolExecutor
- Void execute (Runnable command): executes a task / command without a return value. It is generally used to execute Runnable
- Future submit(Callable task): execute a task with a return value, and generally execute a Callable task
- void shutdown(): closes the connection pool
- Executors: tool class and factory class of thread pool, which are used to create and return different types of thread pools
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //Test thread pool public class TestPool { public static void main(String[] args) { //1. Create a service and a thread pool. The parameter is the size of the thread pool ExecutorService service= Executors.newFixedThreadPool(10); //implement service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); //2. Close the link service.shutdown(); } } class MyThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } }
17. Summary
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; //Review and summarize thread creation public class ThreaadNew { public static void main(String[] args) { new MyThread1().start(); new Thread(new MyThread2()).start(); FutureTask<Integer> futureTask=new FutureTask(new MyThread3()); new Thread(futureTask).start(); try { Integer integer=futureTask.get(); System.out.println(integer); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } //1. Inherit Thread class class MyThread1 extends Thread{ @Override public void run() { System.out.println("MyThreadd1"); } } //2. Implement Runnable interface class MyThread2 implements Runnable{ @Override public void run() { System.out.println("MyThreadd2"); } } //3. Implement Callable interface class MyThread3 implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("MyThreadd3"); return 100; } }
Thread synchronized
Thread extension
lock
xecutorService service= Executors.newFixedThreadPool(10);
//Execute
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//2. Close the link
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
# 17. Summary ~~~java import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; //Review and summarize thread creation public class ThreaadNew { public static void main(String[] args) { new MyThread1().start(); new Thread(new MyThread2()).start(); FutureTask<Integer> futureTask=new FutureTask(new MyThread3()); new Thread(futureTask).start(); try { Integer integer=futureTask.get(); System.out.println(integer); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } //1. Inherit Thread class class MyThread1 extends Thread{ @Override public void run() { System.out.println("MyThreadd1"); } } //2. Implement Runnable interface class MyThread2 implements Runnable{ @Override public void run() { System.out.println("MyThreadd2"); } } //3. Implement Callable interface class MyThread3 implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("MyThreadd3"); return 100; } }
Thread synchronized
Thread extension
lock