brief introduction
- This is a note organized in 2021/04/11
- There may be a little more details, but please be patient to read them
- My content and answers are not necessarily the best and most correct. Welcome to your comments for correction and improvement
The difference between throw and throws
- throws, written after the method signature, can declare that multiple exception types are thrown, separated by commas
- Throw can only throw one exception type object at a time inside a method body
throw can be written anywhere in the method try catch finally
The execution characteristics of finally when return exists in exception handling
- If there is a return statement before the finally statement block, the statement part in finally will still be executed.
- If a return statement or exception occurs in the try-catch-finally exception handling mechanism
Execution order:
(1) Return value
A. If there is a return value, it is stored in a local variable
b. Execute jsr directive to jump to final statement
c. Returns from the finally statement up, taking the return value from the previously saved local variable.
(2) Abnormalities
A. Keep exceptions in a local variable
b. Execute jsr directive to jump to final statement
c. Returns from the finally statement and re-throws the exception. - Extension: The jsr command (Java Specification Requests,Java Specification Proposal) has a jumper, Jump Subroutine, that executes the final block before the return statement executes.
System precedes fina block. Execution of code when exit (0) statement
- System.exit(0) is an exit method in the System class that terminates the currently running virtual machine.
- The virtual machine was shut down and the finally block could not be executed.
return exists in try catch finally, and the order in which the code is executed (there are four cases)
1. There is no return in return finally in the try
public class Test1 { public static void main(String[] args) { int i = test1(); System.out.println(i); } //Define a test method private static int test1(){ int num = 10; try { System.out.println("try"); //Executes num+=80, stores it in a local variable, executes the contents of the final statement block, and then executes the return statement. return num+=80; }catch (Exception e){ System.out.println("Catch"); }finally { if(num>20){ System.out.println("num>20:"+num); } System.out.println("finally"); } return num;//Do not execute } }
Program Run Results
try
num>20:90
finally
90
2. Both return in try and finally
public class Test2 { public static void main(String[] args) { //Return value of output test method System.out.println(test()); } public static int test(){ int num = 10; try{ System.out.println("try"); //Do not jump out of try because return statement exists in finally block //Although num+10 is executed here, it is not assigned to num, but stored in a local variable. return num + 10; }catch (Exception e){ System.out.println("catch"); }finally { //Is num unchanged or 10 System.out.println("finally"+num); //Returns num+10 when jumping out, resulting in 20 return num + 10; } } }
Program Run Results
try
finally10
20
3. assignment in finally (return in try, no return in finally)
public class Test3 { public static void main(String[] args) { //Print out the return value of the test method System.out.println(test()); } public static int test(){ int num = 10; try{ System.out.println("try"); //The return statement here stores the value of num before executing, and then executes the contents of finally. //So even assigning num in finally will not affect the final return result return num; }catch (Exception e){ System.out.println("catch"); }finally { System.out.println("finally"+num); num = 100; } return num; } }
Program Run Results
try
finally10
10
4. Package data in classes
//Define a Num class class Num{ int number = 30; } public class Test4 { public static Num method(){ //Create a Num class object Num num = new Num(); try { System.out.println("try"); return num; }catch (Exception e){ System.out.println("catch"); }finally { if(num.number>20) { System.out.println("number>20:"+num.number); } System.out.println("finally"); //Here, the values of member variables in heap memory are modified directly through a num object. num.number = 100; } return num; } public static void main(String[] args) { //The return value of the method method is a Num class object, so its member variable number can be called System.out.println(method().number); } }
Program Run Results
try
number>20:30
finally
100
Assertions (not commonly used)
assert Boolean expression: error message
IDEA opens the assertion, Edit Configurations adds -ea to VM options
- Click the option on the right side of the hammer in the upper right corner of IDEA and select Edit Configurations
- Check the path of the class to which you want to add the assertion function, then add-ea in VM options
public class Test1 { public static void main(String[] args) { int i = 10; assert i!=10 :"assertion failure"; System.out.println("ok..."); } }
Program Run Results
Exception in thread "main" java.lang.AssertionError: Assertion error
at demo04Assert.Test1.main(Test1.java:10)
Basic concepts of concurrency and parallelism
- Concurrent: Two (or more) programs executed in the same time period
- Parallel: Two (or more) programs executed at the same time
Basic concepts of program process threads
- Program: A program is a piece of code, and the program is static.
- Process: Executing an application is a process. Processes are dynamic and have a life cycle.
- Threads: Threads are execution paths within a program and can have more than one.
- The relationship between the three: a program runs at least one process, and a process can have multiple threads.
Thread Scheduling
Timesharing
- All threads take turns using the CPU, evenly allocating each thread's CPU time.
preemptive scheduling
- Prioritize the use of CPU by threads with higher priority. If threads have the same priority, then one is chosen randomly
Java uses preemptive scheduling.
mutex
Mutex locks are used to ensure that only one thread can access a memory area at any time.
Semaphore
- A semaphore is a facility used in a multithreaded environment to ensure that two or more code segments are not called concurrently.
- Threads must acquire a semaphore before entering a critical code segment; Once the critical snippet is complete, the thread must release the semaphore. Other threads that want to enter this critical code segment must wait until the first thread releases the semaphore.
- Description:
Take the operation of a parking lot as an example. For simplicity, assume that the parking lot has only three parking spaces, all three parking spaces are empty at first. If five cars arrive at the same time, the doorman allows three of them to enter directly, then drops down the car block. The rest of the cars have to wait at the entrance, and subsequently the cars have to wait at the entrance. At this time, a car left the parking lot. When the doorman learns, he opens the car Block and puts one outside into it. If he leaves two more cars, he can put two more, so he can go back and forth.
In this parking lot system, parking spaces are public resources, and each car is like a thread, and the gatekeeper is the semaphore.
The difference between a process and a thread
- The processes are independent. Processes are the basic unit of program operation and have independent memory space and system resources.
- Threads may interact. Threads are the smallest unit of process execution and are allocated thread space and resources by the processor.
Thread class
Three ways to create threads
1. Inherit the Thread class
public class TestThread extends Thread{ } public class Test{ public static void main(String[] args){ TestThread testThread = new TestThread(); } }
2. Implement the Runnable interface (recommended)
(1) Write directly the implementation class of a Runnable interface and override the run method of Runnable. This class of object is a parameter to the Thread construction method
public class MyRunnable implements Runnable{ @Override public void run() { } } public class Test{ public static void main(String[] args){ MyRunnable myRunnable = new MyRunnable(); //The Thread class has a constructor that takes a parameter of the object of the implementation class of the Runnable interface //Transform Up by Importing myRunnable Object Thread thread = new Thread(myRunnable); } }
(2) Anonymous internal class
- Use anonymous internal classes directly instead of writing an interface's implementation class separately.
public class Test { public static void main(String[] args) { //Objects of anonymous internal classes as parameters to the Thread constructor Thread thread = new Thread( new Runnable(){ @Override public void run() { System.out.println("Run override"); } } ); } }
(3)Lambda expression
- Use Lambda expression to simplify the next step
public class Test2 { public static void main(String[] args) { Thread thread = new Thread( () -> { System.out.println("Run override"); } ); } }
3. Implement Callable Interface
JDK1. After 5, there was a third way to create threads
import java.util.Random; import java.util.concurrent.Callable; //MyCallable Implementation Class Implements Callable Interface public class MyCallable implements Callable<Integer> { @Override public Integer call() throws Exception { return new Random().nextInt(10); } } //---------------------------------------------------------------------------------------------------------------------------------------------------------- import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; //Test Class public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { //Create MyCallable Object MyCallable myCallable = new MyCallable(); //Create a task futureTask object FutureTask<Integer> integerFutureTask = new FutureTask<Integer>(myCallable); //Create thread Object Thread thread = new Thread(integerFutureTask); //Start Thread thread.start(); //Get the return value of thread execution System.out.println(integerFutureTask.get()); } }
Thread Start
- Show concurrent effect of calling run method
- Thread calls start method: JVM will call run method of this thread
How to stop a thread
1. Stop threads using shared variables
//Inherit the Thread class using the first way to create a thread public class TestThread extends Thread{ //Define flag as true private boolean flag = true; //Customize how to stop threads public void stopThread(){ flag = false; System.out.println("End"); } @Override public void run() { while(flag){ System.out.println("TestThread.run([])Method:"+Thread.currentThread().getName()); } } } //-------------------------------------- Split Line------------------------- //Test Class public class Test { public static void main(String[] args) throws InterruptedException { //Create Thread Object TestThread testThread = new TestThread(); //Start Thread testThread.start(); //Thread sleeps for a while testThread.stopThread(); } }