Java exceptions and threads
abnormal
Exception: refers to an abnormal situation during the execution of the program, which will eventually lead to the abnormal stop of the JVM. The exception mechanism actually helps us find problems in the program. The root class of the exception is java.lang.Throwable, which has two subclasses, java.lang.Error and java.lang.Exception. The usual exception refers to java.lang.Exception.
Throwable system:
Error: a serious error. An error that cannot be handled can only be avoided in advance, like a terminal disease.
Exception: indicates an exception. After an exception is generated, the programmer can correct it through code to make the program continue to run. It must be handled.
Common methods in Throwable:
public void printStackTrace(): print the details of the exception. It includes the type of exception, the reason for the exception, and the location of the exception. printStackTrace must be used in the development and debugging stages.
public String getMessage(): get the reason for the exception. When prompted to the user, the error reason will be prompted.
public String toString(): get the exception type and exception description information (not required).
/* java.lang.Throwable:Class is a superclass for all errors or exceptions in the Java language. Exception:Compile time exceptions, problems in compiling (writing code) java programs RuntimeException:Run time exceptions, problems in the running process of java programs Exception is equivalent to a small problem in the program. Deal with the exception and the program can continue to execute Error:error An error is equivalent to an incurable problem in the program. The source code must be modified before the program can continue to execute */ public class DemoException { public static void main(String[] args) /*throws ParseException*/ { //Exception: compile time exception, which is a problem in compiling (writing code) java programs /*SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//Used to format the date Date date = null; try { date = sdf.parse("1999-0909");//Parse the Date in string format into Date format } catch (ParseException e) { e.printStackTrace(); } System.out.println(date);*/ //RuntimeException: run-time exception, a problem that occurs during the running of a java program /*int[] arr = {1,2,3}; //System.out.println(arr[0]); try { //Code with possible exceptions System.out.println(arr[3]); }catch(Exception e){ //Exception handling logic System.out.println(e); }*/ /* Error:error OutOfMemoryError: Java heap space Memory overflow error. The array created is too large and exceeds the memory allocated to the JVM */ //int[] arr = new int[1024*1024*1024]; //The code must be modified to create a smaller array int[] arr = new int[1024*1024]; System.out.println("Subsequent code"); } }
throw exception
* throw keyword effect: have access to throw Keyword throws the specified exception in the specified method Use format: throw new xxxException("Cause of abnormality"); be careful: 1.throw Keywords must be written inside the method 2.throw After keyword new The object must be Exception perhaps Exception Subclass object of 3.throw Keyword throws the specified exception object,We have to deal with this exception object throw After the keyword is created RuntimeException Or RuntimeException Subclass object of,We don't have to deal with it,Default to JVM handle(Print exception object,Interrupt program) throw A compilation exception is created after the keyword(An error is reported when writing code),We have to deal with this exception,or throws,or try...catch */ public class DemoThrow { public static void main(String[] args) { //int[] arr = null; int[] arr = new int[3]; int e = getElement(arr,3); System.out.println(e); } /* Defines a method to get the element at the specified index of the array Parameters: int[] arr int index In the future (work), we must first verify the validity of the parameters passed by the method If the parameter is illegal, we must throw an exception to inform the caller of the method that there is a problem with the passed parameter be careful: NullPointerException It is a runtime exception. We don't need to handle it. It is handed over to the JVM by default ArrayIndexOutOfBoundsException It is a runtime exception. We don't need to handle it. It is handed over to the JVM by default */ public static int getElement(int[] arr,int index){ /* We can verify the validity of the passed parameter array If the value of array arr is null Then we throw a null pointer exception and tell the caller of the method that "the value of the passed array is null" */ if(arr == null){ throw new NullPointerException("The value of the array passed is null"); } /* We can verify the validity of the passed parameter index If the index range is not within the index range of the array Then we throw an array index out of bounds exception and tell the caller of the method that "the passed index exceeds the range of use of the array" */ if(index<0 || index>arr.length-1){ throw new ArrayIndexOutOfBoundsException("The index passed is out of range for the array"); } int ele = arr[index]; return ele; } }
Object throws an exception
import java.util.Objects; /* Objects Static methods in classes public static <T> T requireNonNull(T obj):View that the specified reference object is not null. Source code: public static <T> T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); return obj; } */ public class DemoObjects { public static void main(String[] args) { method(null); } public static void method(Object obj){ //Judge the validity of the passed parameters to determine whether they are null /*if(obj == null){ throw new NullPointerException("The value of the object passed is null '); }*/ //Objects.requireNonNull(obj); Objects.requireNonNull(obj,"The value of the object passed is null"); } }
Declare exception throws
import java.io.FileNotFoundException; import java.io.IOException; /* throws Keyword: the first method of exception handling, which is handed over to others for handling effect: When an exception object is thrown inside a method, we must deal with the exception object You can use the throws keyword to handle the exception object. The exception object declaration will be thrown to the caller of the method for processing (you will not handle it yourself, but others), and finally handed over to the JVM for processing -- > interrupt processing Use format: used in method declaration Modifier return value type method name (parameter list) throws aaaexcepton, bbbexcepton{ throw new AAAExcepiton("Cause "); throw new BBBExcepiton("Cause "); ... } be careful: 1.throws Keywords must be written at the method declaration 2.throws The Exception declared after the keyword must be an Exception or a subclass of Exception 3.If multiple exception objects are thrown inside the method, multiple exceptions must also be declared after throws If multiple exception objects thrown have a child parent relationship, you can directly declare the parent exception 4.If we call a method that declares that an exception is thrown, we must handle the declared exception Or continue to use the throws declaration to throw it, give it to the caller of the method for processing, and finally give it to the JVM Or try...catch handle the exception yourself */ public class DemoThrows { /* FileNotFoundException extends IOException extends Excepiton If multiple exception objects thrown have a child parent relationship, you can directly declare the parent exception */ //public static void main(String[] args) throws FileNotFoundException,IOException { //public static void main(String[] args) throws IOException { public static void main(String[] args) throws Exception { readFile("c:\\a.tx"); System.out.println("Subsequent code"); } /* Define a method to judge the legitimacy of the transmitted file path If the path is not "c:\a.txt", we will throw the file and tell the caller of the method that the exception object cannot be found be careful: FileNotFoundException It is a compilation exception. If a compilation exception is thrown, it must be handled You can use the throws declaration to throw FileNotFoundException, an exception object, for the caller of the method to handle */ public static void readFile(String fileName) throws FileNotFoundException,IOException{ if(!fileName.equals("c:\\a.txt")){ throw new FileNotFoundException("The file path passed is not c:\\a.txt"); } /* If the path passed is not at the end of. txt Then we throw an IO exception object to tell the caller of the method that the file suffix is wrong */ if(!fileName.endsWith(".txt")){ throw new IOException("The suffix of the file is incorrect"); } System.out.println("There is no problem with the path,read file"); } }
Exception capture try... catch
import java.io.IOException; /* try...catch:The second way of exception handling is to handle exceptions by yourself be careful: 1.try Multiple exception objects may be thrown in, so you can use multiple catch es to handle these exception objects 2.If an exception occurs in try, the exception handling logic in catch will be executed, the processing logic in catch will be executed, and the code after try...catch will continue to be executed If there is no exception in try, the exception handling logic in catch will not be executed, the code in try will be executed, and the code after try...catch will continue to be executed */ public class DemoTryCatch { public static void main(String[] args) { try{ //Code that may cause exceptions readFile("d:\\a.tx"); System.out.println("Resource release"); }catch (IOException e){//catch defines exception variables to receive exception objects thrown in try //Exception handling logic, how to handle the exception object after the exception object //System.out.println("catch - the file suffix passed is not. txt"); /* Throwable Class defines three exception handling methods String getMessage() Returns a short description of this throwable. String toString() Returns the detailed message string for this throwable. void printStackTrace() JVM This method is used by default to print exception objects. The printed exception information is the most comprehensive */ //System.out.println(e.getMessage());// The suffix of the file is incorrect //System.out.println(e.toString());// Rewrite toString java.io.IOException of Object class: the suffix name of the file is incorrect //System.out.println(e);//java.io.IOException: the suffix of the file is incorrect /* java.io.IOException: The suffix of the file is incorrect at com.itheima.demo02.Exception.Demo01TryCatch.readFile(Demo01TryCatch.java:55) at com.itheima.demo02.Exception.Demo01TryCatch.main(Demo01TryCatch.java:27) */ e.printStackTrace(); } System.out.println("Subsequent code"); } /* If the path passed is not at the end of. txt Then we throw an IO exception object to tell the caller of the method that the file suffix is wrong */ public static void readFile(String fileName) throws IOException { if(!fileName.endsWith(".txt")){ throw new IOException("The suffix of the file is incorrect"); } System.out.println("There is no problem with the path,read file"); } }
Code block finally
/* finally Code block be careful: 1.finally It cannot be used alone. It must be used with try 2.finally It is generally used for resource release (resource recovery). No matter whether the program is abnormal or not, the resource should be released (IO) at last */ public class Demo02TryCatchFinally { public static void main(String[] args) { try { //Code that may generate exceptions readFile("c:\\a.tx"); } catch (IOException e) { //Exception handling logic e.printStackTrace(); } finally { //Whether an exception occurs or not, it is executed System.out.println("Resource release"); } } /* If the path passed is not at the end of. txt Then we throw an IO exception object to tell the caller of the method that the file suffix is wrong */ public static void readFile(String fileName) throws IOException { if(!fileName.endsWith(".txt")){ throw new IOException("The suffix of the file is incorrect"); } System.out.println("There is no problem with the path,read file"); } }
Exception in class
/* Exception of child parent class: - If the parent class throws multiple exceptions, when overriding the parent class method, the child class throws the same exception as the parent class, or the child of the parent class exception, or does not throw an exception. - The parent class method does not throw an exception, and the child class cannot throw an exception when overriding the parent class method. At this time, the subclass generates the exception, which can only be caught and processed, and cannot be declared and thrown be careful: When the parent class is abnormal, the child class is abnormal */ public class Fu { public void show01() throws NullPointerException,ClassCastException{} public void show02() throws IndexOutOfBoundsException{} public void show03() throws IndexOutOfBoundsException{} public void show04() throws Exception {} } class Zi extends Fu{ //When a subclass overrides a parent class method, it throws the same exception as the parent class public void show01() throws NullPointerException,ClassCastException{} //A subclass that throws a parent exception when overriding a parent method public void show02() throws ArrayIndexOutOfBoundsException{} //Subclasses do not throw exceptions when overriding parent methods public void show03() {} /* The parent class method does not throw an exception, and the child class cannot throw an exception when overriding the parent class method. */ //public void show04() throws Exception{} //At this time, the subclass generates the exception, which can only be caught and processed, and cannot be declared and thrown public void show04() { try { throw new Exception("Compile time exception"); } catch (Exception e) { e.printStackTrace(); } } }
Multithreading
Concurrency and parallelism
Concurrency: two or more events occur in the same time period.
Parallel: two or more events occur at the same time (at the same time)
Process: refers to an application running in memory. Each process has an independent memory space. An application can run multiple processes at the same time; Process is also an execution process of the program and the basic unit of the system running program; A system running a program is a process from creation, running to extinction.
Thread: a thread is an execution unit in a process. It is responsible for the execution of programs in the current process. There is at least one thread in a process. There can be multiple threads in a process, and this application can also be called a multithreaded program.
In short: after a program runs, there is at least one process, and a process can contain multiple threads
Thread create thread class
//1. Create a subclass of Thread class public class MyThread extends Thread{ //2. Override the run method in the Thread class in the subclass of the Thread class and set the Thread task (what do you want to do to start the Thread?) @Override public void run() { for (int i = 0; i <20 ; i++) { System.out.println("run:"+i); } } } /* The first way to create a multithreaded program: create a subclass of the Thread class java.lang.Thread Class: a class that describes threads. If we want to implement multithreaded programs, we must inherit the Thread class Implementation steps: 1.Create a subclass of the Thread class 2.Override the run method in the Thread class in the subclass of the Thread class and set the Thread task (what do you want to do to start the Thread?) 3.Create a subclass object of the Thread class 4.Call the start method in the Thread class to start a new Thread and execute the run method void start() Start the thread to execute; The Java virtual machine calls the run method of the thread. The result is that two threads run concurrently; The current thread (the main thread) and another thread (the new thread created executes its run method). It is illegal to start a thread multiple times. Especially when the thread has finished execution, it cannot be restarted. java The program belongs to preemptive scheduling. The thread has high priority and the thread has priority to execute; At the same priority, select one execution at random */ public class DemoThread { public static void main(String[] args) { //3. Create subclass objects of Thread class MyThread mt = new MyThread(); //4. Call the start method in the Thread class to start a new Thread and execute the run method mt.start(); for (int i = 0; i <20 ; i++) { System.out.println("main:"+i); } } }
Ruable create thread class
//1. Create an implementation class of Runnable interface public class RunnableImpl implements Runnable{ //2. Rewrite the run method of the Runnable interface in the implementation class to set the thread task @Override public void run() { for (int i = 0; i <20 ; i++) { System.out.println(Thread.currentThread().getName()+"-->"+i); } } } //1. Create an implementation class of Runnable interface public class RunnableImpl2 implements Runnable{ //2. Rewrite the run method of the Runnable interface in the implementation class to set the thread task @Override public void run() { for (int i = 0; i <20 ; i++) { System.out.println("HelloWorld"+i); } } } /* The second way to create a multithreaded program is to implement the Runnable interface java.lang.Runnable Runnable Interfaces should be implemented by classes that intend to execute their instances through a thread. Class must define a parameterless method called run. java.lang.Thread Class construction method Thread(Runnable target) Assign a new Thread object. Thread(Runnable target, String name) Assign a new Thread object. Benefits of implementing Runnable interface to create multithreaded programs: 1.The limitation of single inheritance is avoided A class can only inherit one class (a person can only have one parent). If a class inherits Thread class, it cannot inherit other classes The Runnable interface is implemented. You can also inherit other classes and implement other interfaces 2.It enhances the expansibility of the program and reduces the coupling (decoupling) of the program The way to implement the Runnable interface separates (decouples) setting the thread task from starting a new thread In the implementation class, the run method is overridden: it is used to set the thread task Create a Thread class object and call the start method: used to start a new Thread */ public class DemoRunnable { public static void main(String[] args) { //3. Create an implementation class object of Runnable interface RunnableImpl run = new RunnableImpl(); //4. Create a Thread class object and construct the implementation class object passing the Runnable interface in the method //Thread t = new Thread(run);// Print thread name Thread t = new Thread(new RunnableImpl2());//Print HelloWorld //5. Call the start method in the Thread class to start a new Thread to execute the run method t.start(); for (int i = 0; i <20 ; i++) { System.out.println(Thread.currentThread().getName()+"-->"+i); } } }
Methods commonly used in threads
public String getName() :Gets the name of the current thread. public void start() :Causes this thread to start executing; Java The virtual machine calls this thread run method. public void run() :The tasks to be performed by this thread define the code here. public static void sleep(long millis) :Pauses (temporarily stops execution) the currently executing thread for the specified number of milliseconds. public static Thread currentThread() :Returns a reference to the thread object currently executing.
/* Get the name of the thread: 1.Use the method getName() in the Thread class String getName() Returns the name of the thread. 2.You can first get the thread currently executing, and use the method getName() in the thread to get the name of the thread static Thread currentThread() Returns a reference to the thread object currently executing. */ // Define a subclass of Thread class public class MyThread extends Thread{ //Override the run method in the Thread class to set the Thread task @Override public void run() { //Get thread name //String name = getName(); //System.out.println(name); //Thread t = Thread.currentThread(); //System.out.println(t);//Thread[Thread-0,5,main] //String name = t.getName(); //System.out.println(name); //Chain programming System.out.println(Thread.currentThread().getName()); } } public class DemoGetThreadName { public static void main(String[] args) { //Create a subclass object of the Thread class MyThread mt = new MyThread(); //Call the start method to start a new thread and execute the run method mt.start(); new MyThread().start(); new MyThread().start(); //Chain programming System.out.println(Thread.currentThread().getName()); } }
/* Set the name of the thread: (learn) 1.Use the method setname (name) in the Thread class void setName(String name) Change the thread name to be the same as the parameter name. 2.Create a construction method with parameters, and pass the name of the thread with parameters; Call the parameterized construction method of the parent class, pass the thread name to the parent class, and let the parent class (Thread) give a name to the child thread Thread(String name) Assign a new Thread object. */ public class MyThread extends Thread{ public MyThread(){} public MyThread(String name){ super(name);//Pass the thread name to the parent class and let the parent class (Thread) give a name to the child thread } @Override public void run() { //Gets the name of the thread System.out.println(Thread.currentThread().getName()); } } public class DemoSetThreadName { public static void main(String[] args) { //Turn on Multithreading MyThread mt = new MyThread(); mt.setName("cockroach"); mt.start(); //Turn on Multithreading new MyThread("Wangcai").start(); } }
/* public static void sleep(long millis):Pauses (temporarily stops execution) the currently executing thread for the specified number of milliseconds. After the end of milliseconds, the thread continues to execute */ public class DemoSleep { public static void main(String[] args) { //Analog stopwatch for (int i = 1; i <=60 ; i++) { System.out.println(i); //Use the sleep method of Thread class to make the program sleep for 1 second try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Anonymous internal creation thread
/* Creating threads by anonymous inner classes Anonymous: no name Inner class: a class written inside other classes Anonymous inner class function: simplify code Inherit the subclass from the parent class, override the methods of the parent class, and create subclass objects in one step The implementation class implements the class interface, rewrites the methods in the interface, creates the implementation class object, and synthesizes it in one step The end product of anonymous inner classes: subclass / implementation class objects, and this class has no name Format: new Parent class / interface (){ Duplicate methods in parent class / interface }; */ public class DemoInnerClassThread { public static void main(String[] args) { //The parent class of a Thread is Thread // new MyThread().start(); new Thread(){ //Override the run method to set the thread task @Override public void run() { for (int i = 0; i <20 ; i++) { System.out.println(Thread.currentThread().getName()+"-->"+"dark horse"); } } }.start(); //Thread interface Runnable //Runnable r = new RunnableImpl(); / / polymorphic Runnable r = new Runnable(){ //Override the run method to set the thread task @Override public void run() { for (int i = 0; i <20 ; i++) { System.out.println(Thread.currentThread().getName()+"-->"+"programmer"); } } }; new Thread(r).start(); //Ways to simplify interfaces new Thread(new Runnable(){ //Override the run method to set the thread task @Override public void run() { for (int i = 0; i <20 ; i++) { System.out.println(Thread.currentThread().getName()+"-->"+"Intelligence Podcast"); } } }).start(); } }
Thread safe - synchronous code block
/* There is a thread safety problem in the ticket selling case Sold non-existent tickets and duplicate tickets A solution to thread safety problem: use synchronous code blocks Format: synchronized(Lock object) {code that may cause thread safety problems (code that accesses shared data)} be careful: 1.Any object can be used through the lock object in the code block 2.However, it must be ensured that the lock object used by multiple threads is the same 3.Lock object function: Lock the synchronization code block and let only one thread execute in the synchronization code block */ public class RunnableImpl implements Runnable{ //Define a ticket source shared by multiple threads private int ticket = 100; //Create a lock object Object obj = new Object(); //Set thread task: selling tickets @Override public void run() { //Use the dead loop to repeat the ticket selling operation while(true){ //Synchronous code block synchronized (obj){ //First judge whether the ticket exists if(ticket>0){ //Improve the probability of safety problems and let the program sleep try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //Ticket exists, ticket selling-- System.out.println(Thread.currentThread().getName()+"-->Selling the third"+ticket+"Ticket"); ticket--; } } } } } /* Simulated ticket selling case Create three threads and start them at the same time to sell the shared tickets */ public class DemoTicket { 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 object passing the Runnable interface in the method Thread t0 = new Thread(run); Thread t1 = new Thread(run); Thread t2 = new Thread(run); //Call the start method to start multithreading t0.start(); t1.start(); t2.start(); } }
Thread safety synchronization method
public class RunnableImpl implements Runnable{ //Define a ticket source shared by multiple threads private static int ticket = 100; //Set thread task: selling tickets @Override public void run() { System.out.println("this:"+this);//this:com.itheima.demo08.Synchronized.RunnableImpl@58ceff1 //Use the dead loop to repeat the ticket selling operation while(true){ payTicketStatic(); } } /* Static synchronization method Who is the lock object? It can't be this this It is generated after the object is created, and the static method takes precedence over the object The lock object of the static method is the class attribute -- > class file object (reflection) of this class */ public static /*synchronized*/ void payTicketStatic(){ synchronized (RunnableImpl.class){ //First judge whether the ticket exists if(ticket>0){ //Improve the probability of safety problems and let the program sleep try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //Ticket exists, ticket selling-- System.out.println(Thread.currentThread().getName()+"-->Selling the third"+ticket+"Ticket"); ticket--; } } } /* Define a synchronization method Synchronous methods also lock the code inside the method Let only one thread execute Who is the lock object of the synchronization method? Is to implement the class object new RunnableImpl() It's this */ public /*synchronized*/ void payTicket(){ synchronized (this){ //First judge whether the ticket exists if(ticket>0){ //Improve the probability of safety problems and let the program sleep try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } //Ticket exists, ticket selling-- System.out.println(Thread.currentThread().getName()+"-->Selling the third"+ticket+"Ticket"); ticket--; } } } } public class DemoTicket { public static void main(String[] args) { //Create an implementation class object for the Runnable interface RunnableImpl run = new RunnableImpl(); System.out.println("run:"+run);//run:com.itheima.demo08.Synchronized.RunnableImpl@58ceff1 //Create a Thread class object and construct the implementation class object passing the Runnable interface in the method Thread t0 = new Thread(run); Thread t1 = new Thread(run); Thread t2 = new Thread(run); //Call the start method to start multithreading t0.start(); t1.start(); t2.start(); } }
Lock lock
java.util.concurrent.locks.Lock mechanism provides a wider range of locking operations than synchronized code blocks and synchronized methods. Synchronized code blocks / synchronized methods have Lock functions. In addition, they are more powerful and object-oriented.
Lock lock is also known as synchronous lock. The locking and releasing methods are as follows:
public void lock(): add synchronization lock.
public void unlock(): release the synchronization lock
/* There is a thread safety problem in the ticket selling case Sold non-existent tickets and duplicate tickets Three solutions to thread safety: using Lock lock java.util.concurrent.locks.Lock Interface Lock The implementation provides a wider range of locking operations than can be obtained using synchronized methods and statements. Lock Methods in the interface: void lock()Get lock. void unlock() Release the lock. java.util.concurrent.locks.ReentrantLock implements Lock Interface Use steps: 1.Create a ReentrantLock object at the member location 2.Call lock in the Lock interface before getting code for security problems. 3.Call the method unlock release lock in the Lock interface after the code that may have security problems. */ public class RunnableImpl implements Runnable{ //Define a ticket source shared by multiple threads private int ticket = 100; //1. Create a ReentrantLock object at the member location Lock l = new ReentrantLock(); //Set thread task: selling tickets @Override public void run() { //Use the dead loop to repeat the ticket selling operation while(true){ //2. call the lock in the Lock interface before getting code for security problems. l.lock(); //First judge whether the ticket exists if(ticket>0){ //Improve the probability of safety problems and let the program sleep try { Thread.sleep(10); //Ticket exists, ticket selling-- System.out.println(Thread.currentThread().getName()+"-->Selling the third"+ticket+"Ticket"); ticket--; } catch (InterruptedException e) { e.printStackTrace(); }finally { //3. call the method unlock release lock in the Lock interface after the code that may have security problems. l.unlock();//The lock will be released whether the program is abnormal or not } } } } public class DemoTicket { 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 object passing the Runnable interface in the method Thread t0 = new Thread(run); Thread t1 = new Thread(run); Thread t2 = new Thread(run); //Call the start method to start multithreading t0.start(); t1.start(); t2.start(); } }
Communication between threads
/* Wait for wake-up case: communication between threads Create a customer thread (consumer): inform the boss of the type and quantity of steamed stuffed buns to be, call the wait method, give up cpu execution, and enter the WAITING state (unlimited WAITING) Create a boss thread (producer): it takes 5 seconds to make a stuffed buns. After doing the steamed stuffed buns, call the notify method to wake customers to eat baozi. be careful: The customer and boss threads must be wrapped in synchronous code blocks to ensure that only one of the wait and wake-up can be executed Lock objects used synchronously must be unique Only lock objects can call the wait and notify methods Obejct Methods in classes void wait() Causes the current thread to wait before another thread calls the notify() method or notifyAll() method of this object. void notify() Wake up a single thread waiting on this object monitor. Will continue to execute the code after the wait method */ public class DemoWaitAndNotify { public static void main(String[] args) { //Create a lock object to ensure uniqueness Object obj = new Object(); // Create a customer thread (consumer) new Thread(){ @Override public void run() { //I've been waiting to buy steamed stuffed buns while(true){ //To ensure that there is only one execution of waiting and waking threads, synchronization technology needs to be used synchronized (obj){ System.out.println("Tell the boss the type and quantity of steamed buns you want"); //Call the wait method, abandon cpu execution, and enter the WAITING state (infinite wait) try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } //Code executed after wake-up System.out.println("The steamed stuffed bun is ready,Eat!"); System.out.println("---------------------------------------"); } } } }.start(); //Create a boss thread (producer) new Thread(){ @Override public void run() { //Keep making steamed stuffed buns while (true){ //It took five seconds to make steamed stuffed buns try { Thread.sleep(5000);//Take five seconds to make steamed stuffed buns } catch (InterruptedException e) { e.printStackTrace(); } //To ensure that there is only one execution of waiting and waking threads, synchronization technology needs to be used synchronized (obj){ System.out.println("The boss will make steamed stuffed buns in five seconds,Inform the customer,You can eat steamed stuffed buns"); //After making the steamed stuffed buns, call notify method to wake customers to eat baozi. obj.notify(); } } } }.start(); } }
/* There are two ways to enter timewaiting 1.Using the sleep(long m) method, after the end of the millisecond value, the thread wakes up and enters the Runnable/Blocked state 2.Use the wait(long m) method. If the wait method is not awakened by notify after the end of the millisecond value, it will automatically wake up, and the thread will wake up and enter the Runnable/Blocked state Wake up method: void notify() Wake up a single thread waiting on this object monitor. void notifyAll() Wake up all threads waiting on this object monitor. */ public class DemoWaitAndNotify { public static void main(String[] args) { //Create a lock object to ensure uniqueness Object obj = new Object(); // Create a customer thread (consumer) new Thread(){ @Override public void run() { //I've been waiting to buy steamed stuffed buns while(true){ //To ensure that there is only one execution of waiting and waking threads, synchronization technology needs to be used synchronized (obj){ System.out.println("Customer 1 told the boss the type and quantity of steamed buns he wanted"); //Call the wait method, abandon cpu execution, and enter the WAITING state (infinite wait) try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } //Code executed after wake-up System.out.println("The steamed stuffed bun is ready,Customer 1 starts eating!"); System.out.println("---------------------------------------"); } } } }.start(); // Create a customer thread (consumer) new Thread(){ @Override public void run() { //I've been waiting to buy steamed stuffed buns while(true){ //To ensure that there is only one execution of waiting and waking threads, synchronization technology needs to be used synchronized (obj){ System.out.println("Customer 2 told the boss the type and quantity of steamed buns he wanted"); //Call the wait method, abandon cpu execution, and enter the WAITING state (infinite wait) try { obj.wait(); } catch (InterruptedException e) { e.printStackTrace(); } //Code executed after wake-up System.out.println("The steamed stuffed bun is ready,Customer 2 open to eat!"); System.out.println("---------------------------------------"); } } } }.start(); //Create a boss thread (producer) new Thread(){ @Override public void run() { //Keep making steamed stuffed buns while (true){ //It took five seconds to make steamed stuffed buns try { Thread.sleep(5000);//Take five seconds to make steamed stuffed buns } catch (InterruptedException e) { e.printStackTrace(); } //To ensure that there is only one execution of waiting and waking threads, synchronization technology needs to be used synchronized (obj){ System.out.println("The boss will make steamed stuffed buns in five seconds,Inform the customer,You can eat steamed stuffed buns"); //After making the steamed stuffed buns, call notify method to wake customers to eat baozi. //obj.notify();// If there are multiple waiting threads, wake up one at random obj.notifyAll();//Wake up all waiting threads } } } }.start(); } }
Thread pool
/* 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"); } } import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /* Thread pool: provided after JDK 1.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 DemoThreadPool { 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 } }
Lambda expression
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:
1. 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 enabled only when the abstract methods in the interface exist and are unique.
2. The use of 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.
Use of Lambda
/* Lambda Standard format for expressions: It consists of three parts: a.Some parameters b.An arrow c.A piece of code Format: (Parameter list) - > {code of some rewriting methods}; Format of explanation: ():The parameter list of the abstract method in the interface is empty if there are no parameters; If there are parameters, write out the parameters. Multiple parameters are separated by commas ->:Pass the parameter to the method body {} {}:Override the method body of the abstract method of the interface */ public class DemoLambda { 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(); } } /* 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"); } }
Lambda, no parameter, no return value
/* 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(); } public class DemoCook { 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(); } }
Lambda has parameters and return values
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 DemoArrays { public static void main(String[] args) { //Use an array to store multiple Person objects Person[] arr = { new Person("Zhang San",38), new Person("Li Si",18), new Person("WangTwo ",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); } } } 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; } }