1, Wait for wake-up mechanism
1. Inter thread communication
2. Overview of waiting wake-up mechanism
What is the waiting wake-up mechanism?
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 some tasks.
After a thread performs a specified operation, it enters the wait state (wait()) and waits for other threads to wake up after executing 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.
Methods in waiting for wake-up:
The wake-up waiting mechanism is used to solve the problem of inter thread communication. The meanings of the three methods used are as follows:
- 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, "notify" the threads WAITING on this object to be released from the wait set and re-enter the ready queue;
- 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;
- notifyAll: release all threads on the wait set of the notified object.
be careful:
Even if only one waiting thread is notified, the notified thread cannot resume execution immediately, because the place where it was interrupted was in the synchronization block, and now it does not hold the lock, so she needs to try to obtain the lock again (probably facing competition from other threads). Only after success can it be called at the beginning
Resume execution after the wait method.
The summary is as follows:
- If the lock can be obtained, the thread will change from WAITING state to RUNNABLE state;
- Otherwise, when it comes out of the wait set and enters the entry set, the thread will change from the WAITING state to the BLOCKED state
Details of calling wait and notify methods:
- 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;
- 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;
- 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.
3. Demand analysis of waiting wake-up mechanism (producer and consumer issues)
4. Wait for the wake-up mechanism code to implement the package subclass & package shop class
package com.itheima.demo01.WaitAndNotify; /* Resource class: package subclass Set the properties of the package skin Sink Status of steamed stuffed bun: true but not false */ public class BaoZi { //skin String pi; //Sink String xian; //Status of steamed stuffed bun: true but not false. Set the initial value to false and there is no steamed stuffed bun boolean flag = false; }
package com.itheima.demo01.WaitAndNotify; /* Producer (steamed stuffed bun shop) class: it is a Thread class that can inherit Thread Set up thread task (run): produce package Judge the state of steamed stuffed bun true:There are steamed stuffed buns The package store calls the wait method to enter the waiting state false:No steamed stuffed bun Steamed buns shop produces steamed buns Add some fun: produce two kinds of steamed stuffed buns alternately There are two states (i%2==0) The steamed stuffed bun shop has produced steamed stuffed buns Modify the status of the steamed stuffed bun to true Wake up the eating thread and let the eating thread eat steamed stuffed buns be careful: Relationship between package sub thread and package sub thread -- > communication (mutually exclusive) Synchronization technology must be used at the same time to ensure that only one of the two threads is executing The lock object must be unique. You can use the package sub object as the lock object The steamed stuffed bun shop class and the food class need to pass in the steamed stuffed bun object as a parameter 1.You need to create a package sub variable at the member location 2.Use the construction method with parameters to assign a value to this package sub variable */ public class BaoZiPu extends Thread{ //1. You need to create a package sub variable at the member location private BaoZi bz; //2. Use the construction method with parameters to assign a value to this package sub variable public BaoZiPu(BaoZi bz) { this.bz = bz; } //Set up thread task (run): produce package @Override public void run() { //Define a variable int count = 0; //Let the steamed stuffed bun shop produce steamed stuffed buns all the time while(true){ //Synchronization technology must be used at the same time to ensure that only one of the two threads is executing synchronized (bz){ //Judge the state of steamed stuffed bun if(bz.flag==true){ //The package store calls the wait method to enter the waiting state try { bz.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //After being awakened, the steamed stuffed bun shop produces steamed stuffed buns //Add some fun: produce two kinds of steamed stuffed buns alternately if(count%2==0){ //Production of thin skinned steamed stuffed buns with three delicacies bz.pi = "Thin skin"; bz.xian = "Three fresh fillings"; }else{ //Production of frozen beef and scallion bz.pi = "Ice skin"; bz.xian = "Beef and scallion"; } count++; System.out.println("The steamed stuffed bun shop is in production:"+bz.pi+bz.xian+"steamed stuffed bun"); //It takes three seconds to produce steamed stuffed buns try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } //The steamed stuffed bun shop has produced steamed stuffed buns //Modify the status of the steamed stuffed bun to true bz.flag = true; //Wake up the eating thread and let the eating thread eat steamed stuffed buns bz.notify(); System.out.println("The steamed stuffed bun shop has been produced:"+bz.pi+bz.xian+"steamed stuffed bun,You can start eating"); } } } }
5. Wait for the wake-up mechanism code to implement the food class & test class
package com.itheima.demo01.WaitAndNotify; /* Consumer (food) class: a Thread class that can inherit Thread Set thread task (run): eat steamed stuffed bun Judge the state of steamed stuffed bun false:No steamed stuffed bun Call the wait method to enter the waiting state after eating true:There are steamed stuffed buns Eat steamed stuffed bun Eat steamed stuffed bun Modify the status of the package to false Eat goods to wake up the thread of steamed stuffed bun shop and produce steamed stuffed buns */ public class ChiHuo extends Thread{ //1. You need to create a package sub variable at the member location private BaoZi bz; //2. Use the construction method with parameters to assign a value to this package sub variable public ChiHuo(BaoZi bz) { this.bz = bz; } //Set thread task (run): eat steamed stuffed bun @Override public void run() { //Use the dead cycle to make the food eat steamed stuffed buns all the time while (true){ //Synchronization technology must be used at the same time to ensure that only one of the two threads is executing synchronized (bz){ //Judge the state of steamed stuffed bun if(bz.flag==false){ //Call the wait method to enter the waiting state after eating try { bz.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //Code executed after being awakened, eat steamed stuffed buns System.out.println("The food is eating:"+bz.pi+bz.xian+"Steamed stuffed bun"); //Eat steamed stuffed bun //Modify the status of the package to false bz.flag = false; //Eat goods to wake up the thread of steamed stuffed bun shop and produce steamed stuffed buns bz.notify(); System.out.println("The food has been taken away:"+bz.pi+bz.xian+"My steamed stuffed bun is finished,The steamed stuffed bun shop began to produce steamed stuffed buns"); System.out.println("----------------------------------------------------"); } } } }
package com.itheima.demo01.WaitAndNotify; /* Test class: Contains the main method, the entry of program execution, and starts the program Create a package sub object; Create buns shop thread, start and produce buns; Create a food thread, open it and eat steamed stuffed buns; */ public class Demo { public static void main(String[] args) { //Create a package sub object; BaoZi bz =new BaoZi(); //Create buns shop thread, start and produce buns; new BaoZiPu(bz).start(); //Create a food thread, open it and eat steamed stuffed buns; new ChiHuo(bz).start(); } }
2, Thread pool
1. Concept and principle of thread pool
- Thread pool: in fact, it is a container containing multiple threads, in which threads can be used repeatedly, eliminating the operation of frequently creating thread objects and consuming too many resources without repeatedly creating threads.
2. Code implementation of thread pool
package com.itheima.demo02.ThreadPool; /* 2.Create a class, implement the Runnable interface, rewrite the run method, and set the thread task */ public class RunnableImpl implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"A new thread execution is created"); } }
package com.itheima.demo02.ThreadPool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /* Thread pool: jdk1 Provided after 5 java.util.concurrent.Executors:The factory class of thread pool, which is used to generate thread pool Executors Static methods in class: static ExecutorService newFixedThreadPool(int nThreads) Create a reusable thread pool with a fixed number of threads Parameters: int nThreads:Create the number of threads contained in the thread pool Return value: ExecutorService Interface, which returns the implementation class object of the ExecutorService interface. We can use the ExecutorService interface to receive (interface oriented programming) java.util.concurrent.ExecutorService:Thread pool interface It is used to obtain threads from the thread pool, call the start method and execute thread tasks submit(Runnable task) Submit a Runnable task for execution Method of closing / destroying thread pool void shutdown() Steps for using thread pool: 1.Use the static method newFixedThreadPool provided in the factory class Executors of thread pool to produce a thread pool with a specified number of threads 2.Create a class, implement the Runnable interface, rewrite the run method, and set the thread task 3.Call the method submit in ExecutorService, transfer the thread task (implementation class), start the thread and execute the run method 4.Call the method shutdown in ExecutorService to destroy the thread pool (not recommended) */ public class Demo01ThreadPool { public static void main(String[] args) { //1. Use the static method newFixedThreadPool provided in the factory class Executors of thread pool to produce a thread pool with a specified number of threads ExecutorService es = Executors.newFixedThreadPool(2); //3. Call the method submit in ExecutorService, transfer the thread task (implementation class), start the thread and execute the run method es.submit(new RunnableImpl());//pool-1-thread-1 creates a new thread execution //The thread pool will always be open. After using the thread, it will automatically return the thread to the thread pool, and the thread can continue to be used es.submit(new RunnableImpl());//pool-1-thread-1 creates a new thread execution es.submit(new RunnableImpl());//pool-1-thread-2 creates a new thread execution //4. Call the method shutdown in ExecutorService to destroy the thread pool (not recommended) es.shutdown(); es.submit(new RunnableImpl());//Throw an exception, the thread pool is gone, and the thread cannot be obtained } }
3, Lambda expression
1. Overview of functional programming ideas
In mathematics, a function is a set of calculation schemes with input and output, that is, "what to do with". Relatively speaking, object-oriented overemphasizes that "things must be done in the form of objects", while functional thinking tries to ignore the complex object-oriented syntax - emphasizing what to do rather than what form to do.
- Object - oriented thinking: do a thing, find an object that can solve it, call the method of the object, and finish it
- Functional programming thought: as long as the results can be obtained, it doesn't matter who does it or how to do it. It pays attention to the results rather than the process
2. Redundant Runnable code
package com.itheima.demo03.Lambda; /* Create the implementation class of the Runnable interface, rewrite the run method, and set the thread task */ public class RunnableImpl implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+" New thread created"); } }
package com.itheima.demo03.Lambda; /* The multithreaded program is implemented by implementing the Runnable interface */ public class Demo01Runnable { public static void main(String[] args) { //Create an implementation class object for the Runnable interface RunnableImpl run = new RunnableImpl(); //Create a Thread class object and construct the implementation class that passes the Runnable interface in the method Thread t = new Thread(run); //Call the start method to start a new thread and execute the run method t.start(); //Simplify the code, use anonymous internal classes, and implement multithreaded programs Runnable r = new Runnable(){ @Override public void run() { System.out.println(Thread.currentThread().getName()+" New thread created"); } }; new Thread(r).start(); //Simplified code new Thread(new Runnable(){ @Override public void run() { System.out.println(Thread.currentThread().getName()+" New thread created"); } }).start(); } }
3. Transformation of programming ideas & experience the better writing method of Lambda
package com.itheima.demo03.Lambda; public class Demo02Lambda { public static void main(String[] args) { //Use anonymous inner classes to realize multithreading new Thread(new Runnable(){ @Override public void run() { System.out.println(Thread.currentThread().getName()+" New thread created"); } }).start(); //Use Lambda expression to realize multithreading new Thread(()->{ System.out.println(Thread.currentThread().getName()+" New thread created"); } ).start(); } } //Optimize Lambda new Thread(()->System.out.println(Thread.currentThread().getName()+" New thread created")).start();
4.Lambda standard format
Lambda Standard format for expressions: It consists of three parts: a.Some parameters b.An arrow c.A piece of code format: (parameter list) -> {Some code for rewriting methods}; Explanation format: ():Parameter list of abstract method in interface,No parameters,It's empty;Write out parameters if there are parameters,Multiple parameters are separated by commas ->:Meaning of transmission,Pass parameters to the method body{} {}:Override the method body of the abstract method of the interface
5. Practice of no parameter and no return value of lambda expression
package com.itheima.demo04.Lambda; /* Set a Cook interface with the only abstract method makeFood */ public interface Cook { //Defines a method makeFood that has no parameters and no return value public abstract void makeFood(); }
package com.itheima.demo04.Lambda; /* Requirements: Given a Cook interface, it contains the only abstract method makeFood, with no parameters and no return value. Use Lambda's standard format to call the invokeCook method and print out "eat!" word */ public class Demo01Cook { public static void main(String[] args) { //Call the invokeCook method. The parameter is the Cook interface. Pass the anonymous inner class object of the Cook interface invokeCook(new Cook() { @Override public void makeFood() { System.out.println("ate"); } }); //Use Lambda expressions to simplify the writing of anonymous inner classes invokeCook(()->{ System.out.println("ate"); }); //Optimize Lambda invokeCook(()-> System.out.println("ate")); } //Define a method, pass the parameters to the Cook interface, and call the method makeFood in the Cook interface inside the method public static void invokeCook(Cook cook){ cook.makeFood(); } }
6. Practice of lambda expression with parameters and return values
package com.itheima.demo05.Lambda; public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
package com.itheima.demo05.Lambda; import java.util.Arrays; /* Lambda Expressions with parameters and return values Requirements: Use an array to store multiple Person objects The Person objects in the array are sorted in ascending order by age using the sort method of Arrays */ public class Demo01Arrays { public static void main(String[] args) { //Use an array to store multiple Person objects Person[] arr = { new Person("Liuyan",38), new Person("Delireba",18), new Person("Gulinaza",19) }; //Use the sort method of Arrays to sort the Person objects in the array in ascending order (front to back) by age /*Arrays.sort(arr, new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge(); } });*/ //Use Lambda expressions to simplify anonymous inner classes Arrays.sort(arr,(Person o1, Person o2)->{ return o1.getAge()-o2.getAge(); }); //Optimize Lambda Arrays.sort(arr,(o1, o2)->o1.getAge()-o2.getAge()); //Traversal array for (Person p : arr) { System.out.println(p); } } }
7. Practice of lambda expression with parameters and return values (user-defined interface)
package com.itheima.demo06.Lambda; /* Given a Calculator calculator interface with an abstract method calc, you can add two int numbers to get the sum value */ public interface Calculator { //Define a method to calculate the sum of two int integers and return the result public abstract int calc(int a,int b); }
package com.itheima.demo06.Lambda; /* Lambda Expressions with parameters and return values Requirements: Given a Calculator calculator interface with an abstract method calc, you can add two int numbers to get the sum value The invokeCalc method is called using Lambda's standard format to complete the addition calculation of 120 and 130 */ public class Demo01Calculator { public static void main(String[] args) { //Call the invokeCalc method. The parameter of the method is an interface. Anonymous inner classes can be used invokeCalc(10, 20, new Calculator() { @Override public int calc(int a, int b) { return a+b; } }); //Simplify writing anonymous inner classes using Lambda expressions invokeCalc(120,130,(int a,int b)->{ return a + b; }); //Optimize Lambda invokeCalc(120,130,(a,b)-> a + b); } /* Define a method Parameter passes two integers of type int Parameter passing Calculator interface Method calls the method calc in the Calculator to calculate the sum of two integers */ public static void invokeCalc(int a,int b,Calculator c){ int sum = c.calc(a,b); System.out.println(sum); } }
8.Lambda omitted format & premise of lambda use
package com.itheima.demo07.Lambda; import java.util.ArrayList; /* Lambda Expression: it is derivable and can be omitted Any content derived from the context can be omitted Contents that can be omitted: 1.(Parameter list): the data type of the parameter list in parentheses, which can be omitted 2.(Parameter list): if there is only one parameter in parentheses, the type and () can be omitted 3.{Some codes}: if there is only one line of code in {}, you can omit ({}, return, semicolon) whether there is a return value or not Note: to omit {}, return, semicolons must be omitted together */ public class Demo01ArrayList { public static void main(String[] args) { //JDK1. Before version 7, you must write the generic types before and after creating a collection object ArrayList<String> list01 = new ArrayList<String>(); //JDK1. After version 7, the generics after the = sign can be omitted, and the generics after the = sign can be derived from the generics before ArrayList<String> list02 = new ArrayList<>(); } }
9. Premise of lambda
Lambda's syntax is very concise and completely free from the constraints of object-oriented complexity. However, there are several problems that need special attention when using:
- Lambda must have an interface, and there must be only one abstract method in the interface.
Whether it is the built-in Runnable, Comparator interface or user-defined interface of JDK, Lambda can be used only when the abstract methods in the interface exist and are unique. - Using Lambda must have context inference.
That is, the parameter or local variable type of the method must be the interface type corresponding to Lambda, and Lambda can be used as an instance of the interface.
Note: an interface with only one abstract method is called "functional interface"