VIII IDEA usage and multithreading

Posted by cmay4 on Wed, 02 Feb 2022 04:33:53 +0100

1. Overview of advanced knowledge points (from Shang School Video)

  1. Chapter 8 multithreading
  2. Chapter 9 common java classes
  3. Chapter 10 enumeration classes and annotations
  4. Chapter 11 java collection
  5. Chapter 12 generics
  6. Chapter 13 IO flow
  7. Chapter 14 network programming
  8. Chapter 15 java reflection mechanism (difficult)
  9. Chapter 16 other new features of Java 8
  10. Chapter 17 new features of Java 9 & 10 & 11

2. Uninstall IDEA perfectly

Two places: ① is the folder where the idea installation directory is located;

② Is the installation path of c disk

Program panel - > uninstall; Find idea, right-click to uninstall and check all. After uninstallation, it is best to restart the computer and reinstall.

3. Use of idea

. exe download custom installation zip decompression for direct use

JDK: development + operation

JRE: running code

Installation process:

Check 64 bits; Uncheck all file associations; Waiting for installation.

idea modify configuration parameters to improve operation fluency:

Under the installation directory: bin - > vmoptions file, open:

-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=512m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-XX:CICompilerCount=2
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-ea
-Dsun.io.useCanonCaches=false
-Djdk.http.auth.tunneling.disabledSchemes=""
-Djdk.attach.allowAttachSelf=true
-Djdk.module.illegalAccess.silent=true
-Dkotlinx.coroutines.debug=off

① Computers with 16G memory can be set to - xms512m (setting the initial number of memory can improve the startup speed of java programs)

② It can also be set to - Xmx1500m (setting the maximum number of memory and increasing this value can reduce the frequency of memory Garage collection and improve program performance)

③ - XX: reservedcodachesize = 512M (indicating the memory capacity occupied by reserved code) does not need to be changed at present

Official download address of IDEA plug-in: https://plugins.jetbrains.com/idea

Create a java project, select the JDK and the storage directory.

tips: enter the statement to output The output code will be automatically created by pressing "sout h" enter.

Understanding and creation of modules

Right click the project name to create a module, and then create function modules and classes under module.

Note, however, that idea project represents a project, and module is just a module, not a project.

4. idea common settings

Enter the settings interface:

4.1 setting theme

  • Set the font and size of forms and menus

Appearance & Behavior

4.2 setting the theme of the editing area

Editor - > color scheme for more topics, download from the website: http://www.riaway.com/ After downloading, import: File - > import settings - > select the downloaded jar file, confirm all the way and restart.

Method 2: install the plug-in.

4.3 setting font size with mouse wheel

Check Change font size with Ctrl + mouse in settings - > editor - > General

4.4 setting the mouse hover prompt

Editor - > General - > appearance - > other check show quick documentation on mouse more, followed by the reaction time ms

4.5 set automatic package guide function

Editor - > General - > auto import - > check both and select Always

4.6 set the separator between the display line number and the method

Editor - > General - > appearance - > show line numbers + show method separators are checked

4.7 ignore case hints

The idea is case sensitive by default. For example, if you enter StringBuffer, the idea will not prompt and supplement the code by default; Unless we enter StringBuffer, we can prompt and supplement. If you don't want to be case sensitive, just change to none.

Editor - > General - > code completion, select none. Or uncheck Match case

4.8 set and cancel the operation of displaying tabs in a single line

When opening many files, idea displays all open file name tab s in a single line by default. Tabs that exceed the interface will be hidden in a single line, which is inefficient and inconvenient to find files.

Editor - > General - > editor tabs uncheck show tabs in one row

4.9 setting default font, font size and font line spacing

Editor - > font, font, size and line spacing can be customized.

4.10 modify the font, font size and line spacing of the current theme in the editing area (ignored)

Editor->Color Scheme->

4.11 setting the output font and size of the console

Editor->Color Scheme->Console Font

4.12 modify the font color of comments in the code

Editor - > Color Scheme - > language defaults - > comments.

4.13 if the number of import s exceeds the specified number, change to*

Editor - > codestyle - > java - > Click Imports in the bar, and enter the number in the bottom two boxes to customize.

4.14 modify the document annotation information of class header

Editor->File and Code Templates

4.15 set project document code

Editor - > file encodings select utf-8

4.16 set the code of the current source file

You can set the code in the lower right corner of the editing area

4.17 setting automatic compilation

Build,Execution,Deployment - > the two items on the right side of compiler, build project automatically and compile independent modules in parallel are checked, that is, the source file is automatically compiled after modification.

4.18 setting power saving mode

If file - > power save mode is checked in the top column, there will be no code prompt and other operations. Don't choose by mistake.

4.19 vertical / horizontal display of two code files

Right click a java file name in the editing area and select split right or split down to display vertically left and right and horizontally up and down respectively.

5. idea shortcut key setting

Settings - > keymap, shortcut key setting, input the function to be realized in the search box on the right, and display the relevant shortcut keys. Enter the shortcut key in the magnifying glass on the right side of the search box to display what function to perform.

Other shortcut keys can also be imported. Select above.

Common shortcut keys

Single line comment: Ctrl +/

Multiline comment: Ctrl + Shift +/

Move line down (display line blocked by interface): Alt + ↓

Move line up (show line blocked by interface): Alt + ↑

Prompt completion: Alt +/

Copy this line to the next line: Ctrl + D

Copy Ctrl + C

Paste Ctrl + V

Cut Ctrl + X

Save Ctrl + S

Undo Ctrl + Z

Undo Ctrl + Y

Select all Ctrl + A

Select several rows and move the tab backward as a whole

Select several rows and move the whole forward by shift + tab

View class inheritance: Ctrl + H

Find: Ctrl + F

Find file: double click shift

Add try/catch or other statement blocks (Surround with): Alt + Shift + Enter!!!

wait.

6. Use of idea template

① Editor - > General - > postfix completion can only be used and is fixed

Code abbreviation automatic call template completion

Such as South 5 For, etc

Southp enter output parameter value

② Editor - > Live Templates there are many templates that can be modified or added by yourself

Such as main method psvm

----------Multithreading-----------

7. Concept of program process thread

  • Program: a set of instructions written in a language that does not complete a specific task. That is, a piece of static code (not running), static object.

  • Process: an execution process of a program or a running program. It is a dynamic process. It has its own life cycle

  • Thread: a process can be further refined into a thread, which is an execution path within a program.

    • If a process executes multiple threads in parallel, it supports multithreading;
    • As a unit of scheduling and execution, each thread has its own running stack and program counter. The overhead of thread switching is smaller than that of the process
    • Multiple threads in the same process share the same memory unit / memory address space - > they allocate objects from the same heap and can access the same variables and objects. Make the communication between threads easier and more efficient. However, the system resources shared by multiple threads may bring security risks (such as resource competition).

8. Single and multi-core CPU understanding and task parallelism and concurrency

  • Single core CPU is actually a fake multithreading, because only one thread can be executed in a time unit. For example, although there are many lanes, there is only one staff member in the toll station (CPU); Multi core can give better play to multi-threaded efficiency.
  • A Java application has at least three threads: main() main thread, gc() garbage collection thread and exception handling thread. If an exception occurs, it will affect the main thread.
  • Parallelism and concurrency

Parallel: multiple CPU s execute multiple tasks at the same time. For example, people do different things at the same time.

Concurrency: one CPU (using time slice) executes multiple tasks at the same time, such as second kill and multiple people doing one thing.

9. Advantages of multithreading

In the case of single core CPU, sending two files at the same time is slower than sending one after another. (because the single core seems to be at the same time, it is actually executed by switching).

Under multi-core, it is faster to send at the same time.

  1. Improve program response., It is more meaningful for graphical interface operation and affects user experience.
  2. Improve computer CPU utilization (no waiting time slice)
  3. Improve program structure. The complex process is divided into multiple threads for easy understanding and modification.

When do I need multithreading?

  • The program needs to perform two or more tasks at the same time
  • When the program needs to realize some tasks that need to wait, such as user input, file reading and writing, network operation, search, etc.
  • When you need some programs running in the background.

10. Create multithreading mode 1: inherit Thread class

A single thread is executed by one line.

  • Java's jvm allows programs to run multiple threads through Java Lang. thread class.

  • Characteristics of Thread class

① Each Thread completes the operation through the run() method of a specific Thread object. The main body of the run() method is often turned into the Thread body

② Start the Thread through the start() method of the Thread object instead of calling run().

//Multithreading creation method 1: inherit Thread class
/*
* 1. Create a subclass that inherits from the Thread class
* 2. Override run() of Thread class
* 3. An object that creates a subclass of the Thread class
* 4. start() is called through this object
* */

//Traverse even numbers within 100
//1. Create a subclass inherited from Thread class
class MyThread  extends Thread {
    //2. Override run() of Thread class
    @Override
    public void run(){
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0){
                System.out.println(i);
            }
        }
    }
}

public class ThreadTest01{
    public static void main(String[] args) {
        //3. Create objects of subclasses of Thread class
        MyThread t1 = new MyThread();
        //4. Call start() through this object
        t1.start();
        
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0){
                System.out.println(i);
            }
        }
    }
}

Analysis: T1 Start() is still executed by the main thread; After that, the run method is automatically executed by the new thread; The following for loop is also executed by the main thread. If the main thread executes faster, it will output odd numbers first; Then output an even number.

11. Description of two problems of creating multithreading

The function of the start() method: ① start the current thread ② call the run() method of the current thread

The run() method of the Thread class was supposed to be executed, but at the same time, the subclass overrides the run() method, so the run() method of the subclass is called.

Question 1: can I use T1 directly Run() starts a new thread, not start()???

A: obviously not. java stipulates that the start() method starts the thread. Calling the run() method directly is only executing the method, not multithreading.

Get the current thread Name: thread currentThread(). getName()

Question 2: start another thread and traverse the even number within 100?

A: it will report an exception. Because the start() method can only be called once. At this time, you need to create a new thread object t2 to call the start() method.

12. Common methods of thread

Related methods of Thread class:

  1. void start() starts the thread and executes the run() method of the object
  2. The operation that the run() thread performs when it is scheduled often needs to override this method
  3. String getName(): returns the name of the thread
  4. void setName(String name): sets the thread name
  5. static Thread currentThread(): returns the current thread.
  6. yield(): release the execution authority of the current CPU
  7. join(): block the current thread, complete the method that joins in first, and then resume the previous execution.
  8. stop(): force the end of the thread. It is obsolete.
  9. Sleep (long Millime): blocking. The thread sleeps for a period of time, in milliseconds
  10. isAlive(): judge whether the current thread is still alive
/*
Common methods of testing Thread class
 */
class Thread01 extends Thread{
    @Override
    public void run(){
        for (int i = 0; i < 20; i++) {
            if (i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class ThreadMethodTest {
    public static void main(String[] args) {
        Thread01 t1 = new Thread01();

        // Name the thread
        t1.setName("Thread 1");
        t1.start();
        //Name the main thread
        Thread.currentThread().setName("main Main thread");
        System.out.println(Thread.currentThread().getName() + ":" + "Ha ha ha");
    }
}

Method 1 of naming thread: T1 Setname ("thread 1");

Method 2 for naming threads:

//The thread is named by constructor overloading in the thread subclass
    public Thread01(String name){
        super(name);
    }
//When a new thread object is created in the main method, the name is passed in as a parameter.
Thread01 t1 = new Thread01("thread000");

13. Thread scheduling (priority)

  • scheduling strategy

Time slice switching mode

Preemptive: high priority threads preempt CPU

  • Scheduling method of Java

Threads with the same priority form a first in, first out queue, first in, first out service, and use the time slice strategy.

For high priority, the preemptive strategy of priority scheduling is used.

  • Priority of thread (3 constants):

MAX_PRIORITY: 10

MIN_PRIORITY: 1

NORM_PRIORITY: the default priority of 5 threads

  • Methods involved

Thread priority (): return priority value

setPriority(): change the priority of the thread

  • explain

When a thread is created, it inherits the priority of the parent thread

Low priority only has a low probability of obtaining scheduling, and is not necessarily called after high priority threads

14. Example: inherit Thread mode and sell tickets in multiple windows

/*
Example: create three windows to sell tickets, and the total number of tickets is 100
 There is a thread safety problem to be solved.
 */
class Window extends Thread{

    private static int ticket = 100; //Declared static, only one share

    @Override
    public void run(){
        while (true){
            if (ticket > 0){
                System.out.println(getName() + ":Ticket number:" + ticket);
                ticket--;
            }else {
                break;
            }
        }
    }
}

public class WindowTest {
    public static void main(String[] args) {
        Window t1 = new Window();
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}

15. Create multithreading mode 2: implement Runnable interface

/*
Create multithreading mode 2: implement runnable interface
1. Create a class that implements the Runnable interface
2. The implementation class implements the abstract method in Runnable: run()
3. Create an object that implements the class
4. Pass this object as a parameter to the constructor of Thread class to create the object of Thread class
5. Start() s is called through the object of Thread class
 */
//1. Create a class that implements the Runnable interface
class MThread implements Runnable{
    //2. Implement the class to implement the abstract method in Runnable: run()
    @Override
    public void run(){
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class RunnableImplTest {
    public static void main(String[] args) {
        //3. Create an object that implements the class
        MThread t1 = new MThread();
        //4. Pass this object as a parameter to the constructor of Thread class and create the object of Thread class
        Thread tt1 = new Thread(t1);
        //5. Call start() through the object of Thread class
        tt1.setName("Thread 1");
        tt1.start();  //Why call the run of the current thread but execute the rewritten run?
        //Because the run() method of the target of runnable type is called in the run of the current thread, and the target at this time is the parameter t1 passed in

        Thread tt2 = new Thread(t1);
        tt2.setName("Thread 2");
        tt2.start();
    }
}

16. Example: realize multi window ticket selling in Runnable mode

/*
Example: create three windows to sell tickets, with a total of 100 tickets. Use the Runnable interface
 There is a thread safety problem to be solved.
 */
class Window1 implements Runnable{

    private int ticket = 100;  //static is not added here. It is still the same ticket. The reason is that only a new object t1 is passed in as a parameter.

    @Override
    public void run(){
        while (true) {
            if (ticket > 0) {
                System.out.println(Thread.currentThread().getName() + "Ticket number:" + ticket);
                ticket--;
            } else {
                break;
            }
        }
    }
}


public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();
        //The three always use the same object
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.start();
        t2.start();
        t3.start();
    }
}

17. Comparison of two creation methods

Interface implementation is more recommended; Inheritance has limitations and cannot inherit other classes

In addition, the interface implementation method does not need to declare variables as static;

  • The method of realizing Runnable interface is preferred in development
  • Reason ① the implementation method has no limitation of single class inheritance
  • Reason ② the implementation method is more suitable for dealing with the situation that multi threads have shared data

In fact, in the source code, the Thread class itself implements the Runnable interface; Both methods need to rewrite the logic to be executed by the Thread in the run() method.

18. Thread life cycle

Thread. Is used in JDK The state class defines several states of a thread.

Several States experienced by a complete life cycle:

  • New: when a Thread class or its subclass object is declared and created, the Thread is in the new state; new
  • Ready: after the newly created thread is started (), it will enter the thread queue and wait for the CPU time slice. At this time, it is ready to run, but it is not allocated to CPU resource start()
  • Run: when the ready thread is scheduled and obtains the CUP resource, it will enter the running state. The run() method defines the operation and function of the thread run()
  • Blocking: in a special case, when it is considered to suspend or execute input / output operations, it gives up the CPU and temporarily terminates its own execution, and enters the blocking state, such as sleep() join() wait() wait for synchronization lock suspend()
  • Death: the thread has completed all its work, or the thread is forcibly suspended in advance or an exception occurs, resulting in the end of the thread stop() or the execution of run() or an exception

19. Understand thread safety

Question:

  • The uncertainty of multi thread execution leads to the instability of execution results
  • The sharing of ledger by multiple threads will cause the incompleteness of operation and destroy the data

Case:

① How to implement Runnable interface

Three windows sell tickets, a total of 100, and three 100 will appear. Duplicate ticket;

When ticket > 0, add sleep to let the thread sleep for a period of time and then output. At this time, each window can sell 100 tickets / wrong tickets;

wait.

The cause of the problem?

When a thread is operating the ticket and the operation has not been completed, other threads participate and operate the ticket.

How to solve it?

When a thread a is in the operation ticket, other threads cannot participate in it. Other threads cannot start to operate the ticket until the thread a is finished. Even if a is blocked, it cannot be changed.

20. The synchronous code block handles the thread safety problem of Runnable mode

In Java, thread safety is solved through synchronization mechanism.

Method 1: synchronize code blocks

keyword:

synchronized(Synchronization monitor){
	//Code to be synchronized
}

tips: code that operates shared data, that is, code that needs to be synchronized.

Shared data: variables operated by multiple threads, such as ticket in ticket sales

Synchronous monitor: commonly known as lock. The object of any class can act as a lock.

Supplement: you can use this to replace the class object of new (provided this is unique)

/*
Example: create three windows to sell tickets, with a total of 100 tickets. Use the Runnable interface
 There is a thread safety problem to be solved.
Use synchronized keyword
1. The number of code blocks that contain shared data cannot be more or less.
2, new An object acts as a lock
3. Requirement: multiple threads share the same lock, so the declaration position of the lock (object) is very important!!! (anonymous class objects are not allowed)
4. Advantages of synchronization: solve thread safety problems; When operating synchronous code, only one thread can participate and other threads wait. It is equivalent to a single thread process, which is inefficient-- Shortcomings.
 */
class Window1 implements Runnable{

    private int ticket = 100;  
    Object obj = new Object(); // 2. Here, a class object is randomly instantiated to act as the following lock
	//You can use this instead of new objects
    @Override
    public void run(){
        while (true) {   //this can be replaced here
            synchronized (obj) {  //1. The following codes need to be synchronized
                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + "Ticket number:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();
        //The three always use the same object
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.start();
        t2.start();
        t3.start();
    }
}

21. The synchronous code block deals with the Thread safety problem of inheriting the Thread class

sleep for a period of time, there is also the problem of duplicate tickets.

Use the synchronized keyword. The above method is solved, and the result is still problematic. Reason: new has three objects, and obj object is not unique.

Solution: declare obj as static type.

Add: be careful to use this as obj here (unless this is unique). You can use the current class name Class substitution

/*
Example: create three windows to sell tickets, with a total of 100 tickets, using the method of inheriting Thread class
 There is a thread safety problem to be solved.
Similarly, the synchronized keyword
 */
class Window extends Thread{

    private static int ticket = 100; //Declared static, only one share

    private static Object obj = new Object(); //obj object is declared as static type!

    @Override
    public void run(){
        while (true){//You cannot replace obj with this here because there are three objects. But there can be another alternative, window Class (class name. class) (take the current class as an example, which proves that the class is also an object!), Avoid new objects
            synchronized (obj) {
                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(getName() + ":Ticket number:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

public class WindowTest {
    public static void main(String[] args) {
        Window t1 = new Window(); //Three class objects are declared
        Window t2 = new Window();
        Window t3 = new Window();

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}

Improvement: is there a relatively simple object that does not need to new an object?

The current object. this. That is, the object of the current class. However, this cannot be used in the Thread class because there are three objects.

Then there is an alternative, that is, the current class name Class replaces obj.

22. The synchronization method deals with the thread safety problem of realizing Runnable mode

That is, if the complete life of the code operating the shared data is in a method, we declare the method synchronous.

Synchronous method: add the synchronized keyword before the return type of the method.

/*
Using synchronization method to solve the thread safety problem of implementing Runnable interface
 */
class Window2 implements Runnable{

    private int ticket = 100;  //static is not added here. It is still the same ticket. The reason is that only a new object w2 is passed in as a parameter.
    private boolean flag = true;
    @Override
    public void run(){
        while (flag) {
            show();
        }
    }

    private synchronized void show(){
        if (ticket > 0) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "Ticket number:" + ticket);
            ticket--;
        }else flag = false;
    }
}

public class WindowTest2 {
    public static void main(String[] args) {
        Window2 w2 = new Window2();
        //The three always use the same object
        Thread t1 = new Thread(w2);
        Thread t2 = new Thread(w2);
        Thread t3 = new Thread(w2);

        t1.start();
        t2.start();
        t3.start();
    }
}

23. The synchronous method deals with the Thread safety problem of inheriting the Thread class

/*
Example: create three windows to sell tickets, with a total of 100 tickets, using the method of inheriting Thread class
 There is a thread safety problem to be solved.
Use the synchronization method to solve the Thread safety problem of inheriting the Thread class
1. The synchronization method still involves the synchronization monitor, but we don't need to display the declaration
2. Non static synchronization method. The synchronization monitor is this
    Static synchronization method. The synchronization monitor is the current class itself.
 */
class Window3 extends Thread{

    private static int ticket = 100; //Declared static, only one share

    @Override
    public void run(){
        while (true){
            show();
        }
    }
    private static synchronized void show(){  //It is written as static type. At this time, the synchronization monitor is unique, but not this. It is the current class Window3 and the current class is unique
    //private synchronized void show() {/ / the synchronization monitors T1, T2 and T3 are not safe at this time
        if (ticket > 0) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + ":Ticket number:" + ticket);
            ticket--;
        }
    }
}

public class WindowTest3 {
    public static void main(String[] args) {
        Window3 t1 = new Window3();
        Window3 t2 = new Window3();
        Window3 t3 = new Window3();

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}

24. Lazy style of thread safe singleton mode

Lazy is not safe; The hungry man style is safe.

Lazy improvement.

/*
Use the synchronization mechanism to rewrite the lazy style in singleton mode to thread safe.
With synchronized, the static method synchronization lock is the class itself
 */
public class BankTest {
}

class Bank{
    private Bank(){}

    private static Bank instance = null;

//    public static synchronized Bank getInstance(){
//        if (instance == null){
//            instance = new Bank();
//        }
//        return instance;
//    }//It is the same as the following, except for the difference between synchronization method and synchronization code block
    public static Bank getInstance() {
        //Method 1: the efficiency is not high. Only the first thread in multiple threads needs to queue up to return to instance after initialization
//        synchronized (Bank.class) {
//            if (instance == null) {
//                instance = new Bank();
//            }
//            return instance;
//        }
        //Mode 2: a slightly higher outer layer is added with a judgment, double check lock, and subsequent threads do not have to queue in
        if (instance == null) {
            synchronized (Bank.class) {
                if (instance == null) {
                    instance = new Bank();
                }
            }
        }
        return instance;
    }
}

25. Multi thread deadlock

  • deadlock
    • Different threads occupy the synchronization resources needed by the other party and do not give up. They are waiting for the other party to give up the synchronization resources they need, forming a thread deadlock
    • After a deadlock occurs, there will be no exception or prompt, but all threads are blocked and cannot continue
  • resolvent
    • Special algorithms and principles
    • Minimize the definition of synchronization resources
    • Try to avoid nested synchronization
/*
Demonstrate thread deadlock
 */
public class ThreadTest {
    public static void main(String[] args) {

        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();

        new Thread(){
            @Override
            public void run(){
                synchronized (s1){
                    s1.append("a");
                    s2.append("1");

                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2){
                    s1.append("c");
                    s2.append("3");

                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();
    }
}

//This output will deadlock, but the probability is small. In addition, the output result is not unique and may be restrictive. The following result is cd 34 cdab 3412
ab
12
abcd
1234

Increase the probability of Deadlock:

sleep 100

/*
Demonstrate thread deadlock
1. Understanding of Deadlock: different threads occupy the synchronization resources required by each other and do not give up,
They are waiting for the other party to give up the synchronization resources they need, forming a thread deadlock
2. Note: deadlock occurs, no exception, no error report, blocking, and cannot continue.
 */
public class ThreadTest {
    public static void main(String[] args) {

        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();

        new Thread(){
            @Override
            public void run(){
                synchronized (s1){
                    s1.append("a");
                    s2.append("1");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s2){
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2){
                    s1.append("c");
                    s2.append("3");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    synchronized (s1){
                        s1.append("d");
                        s2.append("4");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();
    }
}
//At this time, no error is reported or anything is output after operation, and it is stuck and running all the time

Example 2:

class A{
    public synchronized void foo(C b) {
        System.out.println("Current thread Name:" + Thread.currentThread().getName()
                 + "Entered A Instance foo method");
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex){
            ex.printStackTrace();
        }
        System.out.println("Current thread Name:" + Thread.currentThread().getName()
                + "Attempt to call C Instance last method");
        b.last();
    }

    public synchronized void last(){
        System.out.println("Entered A Class last Method internal");
    }
}

class C{
    public synchronized void bar(A a) {
        System.out.println("Current thread Name:" + Thread.currentThread().getName()
                + "Entered C Instance bar method");
        try {
            Thread.sleep(200);
        } catch (InterruptedException ex){
            ex.printStackTrace();
        }
        System.out.println("Current thread Name:" + Thread.currentThread().getName()
                + "Attempt to call A Instance last method");
        a.last();
    }

    public synchronized void last(){
        System.out.println("Entered B Class last Method internal");
    }
}

public class ThreadTest2 implements Runnable{
    A a = new A();
    C b = new C();

    public void init(){
        Thread.currentThread().setName("Main thread");
        a.foo(b);
        System.out.println("After entering the main thread");
    }

    public void run(){
        Thread.currentThread().setName("Secondary thread");
        b.bar(a);
        System.out.println("After entering the secondary thread");
    }

    public static void main(String[] args) {
        ThreadTest2 d1 = new ThreadTest2();
        new Thread(d1).start();  //Adjusting thread run method

        d1.init();  //Calling the init method of the main thread
    }
}

26. The lock mode solves the thread safety problem

  • Starting from JDK5, java provides -- realize synchronization by displaying and defining synchronization Lock objects, which use Lock objects as
  • 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 Lovk object at a time. Threads should obtain the lock object before accessing shared resources
  • ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized. ReentrantLock is commonly used in thread safety control, which can display locking and releasing locks.
/*
Three ways to solve thread safety problems: Lock lock ----- JDK5 definition
 */
class Window4 implements Runnable{
    private int ticket = 100;
    //① Instantiate a lock
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run(){
        while (true){
            try {
                //2. Call the lock method (lock)
                lock.lock();

                if (ticket > 0){

                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":Ticket No.:" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }finally {
                lock.unlock(); //3.  Call the unlocked method
            }

        }
    }
}

public class LockTest {
    public static void main(String[] args) {
        Window4 w = new Window4();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("Window 1");
        t2.setName("Window 2");
        t3.setName("Window 3");

        t1.start();
        t2.start();
        t3.start();
    }
}

Interview question: similarities and differences between synchronized and lock

Same: both solve thread safety problems

Different: synchronized automatically releases the synchronization monitor after executing the response logic; Lock needs to manually start synchronization (lock()) and end synchronization (unlock()).

27. After class practice of synchronization mechanism

Code with thread safety problems:

/*
Title: the bank has an account.
Two depositors deposit 3000 yuan into the account respectively, 1000 yuan each time and three times. Print the account balance after each deposit.

analysis:
1. Is it a multithreading problem? Yes, two depositor threads
2. Is there shared data? Yes, account
3. Are there thread safety issues? yes
4. How to solve it? There are three synchronization mechanisms: Thread, runnable and lock

 */

class Account{

    private double balance;

    public Account(double acct){
        this.balance = balance;
    }

    public void storeMoney(double money){
        if (money > 0){
            balance += money;

            try {
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }


            System.out.println(Thread.currentThread().getName() + ": The deposit is successful, and the balance is:" + balance);
        }
    }
}

class Custom extends Thread{

    private Account acct;

    public Custom(Account acct) {
        this.acct = acct;
    }

    @Override
    public void run(){
        for (int i = 0; i < 3; i++) {
            acct.storeMoney(1000);
        }
    }
}

public class AccountTest {
    public static void main(String[] args) {
        Account acct = new Account(0);
        Custom c1 = new Custom(acct);//Here, this refers to the account, sharing one, so it is available
        Custom c2 = new Custom(acct);

        c1.setName("nail");
        c2.setName("B");

        c1.start();
        c2.start();
    }
}
//
nail: Successful saving, balance: 2000.0
 B: Successful saving, balance: 2000.0
 B: Successful saving, balance: 4000.0
 nail: Successful saving, balance: 4000.0
 nail: Successfully saved money, the balance is 6000.0
 B: Successfully saved money, the balance is 6000.0

Solution: add a synchronized to the method of saving money.

Output:

nail: Successful saving, balance: 1000.0
 nail: Successful saving, balance: 2000.0
 nail: Successful saving, balance: 3000.0
 B: Successful saving, balance: 4000.0
 B: Successful deposit, balance: 5000.0
 B: Successfully saved money, the balance is 6000.0

28. Thread communication

Example: use two threads to print 1-100, and thread 1 and thread 2 print alternately.

Three methods involved:

wait(): when this method is executed, the current thread enters the blocking state and releases the synchronization monitor

notify(): execute this method to wake up a thread wait ing; If there are multiple, wake up the one with higher priority.

notifyAll(): execute this method to wake up all wait ing methods

tips:

  1. wait, notify and notifyAll can only be used in synchronization methods or synchronization code blocks.

  2. These methods are called by this; That is, the object calling them must be a synchronization code block or a synchronization monitor in a synchronization method. Otherwise, an Illegal exception will appear.

  3. These three methods are defined in Java Lang. object class.

/*
Examples of thread communication
 Use two threads to print 1-100, and thread 1 and thread 2 print alternately
 */
class Number implements Runnable{
    private int number = 1;
    @Override
    public void run(){
        while (true){
            synchronized (this) {

                notify(); // Wake up thread 2 wakes up 1 after it comes in, but at this time, 2 holds the lock and 1 cannot enter

                if (number <= 100) {

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":" + number);
                    number++;

                    try {
                        wait();  //Make the thread calling this method enter the blocking state. 2 releases the lock here, and then 1 takes it in (sleep will not release the lock)
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } else {
                    break;
                }
            }
        }
    }
}


public class ThreadPrint {
    public static void main(String[] args) {
        Number num = new Number();
        Thread t1 = new Thread(num);
        Thread t2 = new Thread(num);
        t1.setName("Thread 1");
        t2.setName("Thread 2");

        t1.start();
        t2.start();
    }
}

//
Thread 1:1
 Thread 2:2
 Thread 1:3
 Thread 2:4
...

29. Interview questions and summary

  1. Similarities and differences between sleep and wait methods

Same: once this method is executed, the current thread can enter the blocking state

Difference: ① the positions of the two method declarations are different: sleep() is declared in the Thread class. Declare wait() in the Object class;

Second, the calling requirements are different: sleep() can be invoked in any required scenario, and wait() must be invoked in synchronized block or synchronization method.

③ About whether to release the synchronization monitor: if both methods are used in the synchronization code block or synchronization method, sleep will not be released; wait release.

30. Classic example: Producer / consumer issues

/*
Application of thread communication: classic example: producer consumer problem
 Analysis: it belongs to multithreading problem, producer thread and consumer thread
 Shared data: Clerk (or product)
How to solve: synchronization mechanism, three methods
 Thread communication is involved
 */
class Clerk{

    private int count = 0;
    //yield a product
    public synchronized void produceProduct() {

        if (count < 20){
            count++;
            System.out.println(Thread.currentThread().getName() + ":Start production" + count + "Products");
            notify();//Awaken consumer consumption
        }else{
            //wait for
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //Consumer products
    public synchronized void consumeProduct() {
        if (count > 0){
            System.out.println(Thread.currentThread().getName() + ":Start consumption" + count + "Products");
            count--;
            notify(); //Wake up producers to continue production
        }else{
           //wait for
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

class Producer extends Thread{ // producer

    private Clerk clerk;

    public Producer(Clerk clerk){
        this.clerk = clerk;
    }

    @Override
    public void run(){
        System.out.println(getName() + ": Start production...");
        while (true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.produceProduct();
        }
    }
}

class Consumer extends Thread{ //consumer

    private Clerk clerk;

    public Consumer(Clerk clerk){
        this.clerk = clerk;
    }

    @Override
    public void run(){
        System.out.println(getName() + ": Start consuming products...");
        while (true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.consumeProduct();
        }
    }
}

public class ProductTest {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();

        Producer p1 = new Producer(clerk);
        p1.setName("Producer 1");
        Consumer c1 = new Consumer(clerk);
        c1.setName("Consumer 1");

        p1.start();
        c1.start();
    }
}

31. JDK5.0 new thread creation method 3

  • Method 3: implement the Callable interface, which is more powerful than Runnable

    • Compared with the run() method, call() can have a return value
    • Method can run out of exception
    • Return values that support generics
    • You need to use the FutureTask class to get the returned results, for example
  • Future interface

    • You can cancel the execution results of specific Runnable and Callable tasks, query whether they are completed, obtain results, etc.
    • FutureTask is the only implementation class of the Future interface
    • FutureTask implements both Runnable and Future interfaces. It can be executed by the thread as Runnable or get the return value of Callable as Future
/*
Thread creation mode 3: implement the callable interface----- jdk5.0 NEW
 Steps:
1. Create an implementation class that implements callable
2. Implement the call method and declare the operation that this thread needs to perform in this method
3. Create an object of the Callable interface implementation class
4. Pass the object of this Callable interface implementation class as a parameter to the FutureTask constructor to create the object of FutureTask
5. Pass the FutureTask object as a parameter to the constructor of the Thread class, create the Thread object, and call start()
6. Get the return value of call() in Callable (not in step 6, unless you need to give the result to another thread)

How to understand that the method of implementing Callable interface to create multithread is more powerful than that of implementing Runnable interface to create multithread???
1. call()Method can have a return value and give it to another thread (get())
2. call()Method can throw an exception, be caught by external operations, and obtain exception information
3. Callable It supports generics

 */
//1. Create an implementation class that implements callable
class NumThread implements Callable{
    //2. Implement the call method and declare the operation to be performed by this thread in this method
    @Override
    public Object call() throws Exception {
        int sum = 0;
        //Traverse even numbers within 100 and return the sum of all even numbers
        for (int i = 0; i <= 100; i++) {
            if (i % 2 == 0){
                System.out.println(i);
                sum += i;
            }
        }
        return sum;   //This involves boxing. Int is not a subclass of object. It is equivalent to converting int to integer (a subclass of object)
    }
}

public class ThreadCallableTest {
    public static void main(String[] args) {
        //3. Create an object of the Callable interface implementation class
        NumThread numThread = new NumThread();
        //4. Pass the object of this Callable interface implementation class as a parameter to the FutureTask constructor to create the FutureTask object
        FutureTask futureTask = new FutureTask(numThread);
        //5. Pass the FutureTask object as a parameter to the constructor of the Thread class, create the Thread object, and call start()
        new Thread(futureTask).start();  //The start thread starts executing the call() method

        try {
            //6. Get the return value of call() in Callable
            //The return value of the get method is the return value of call() overridden by the futureTask constructor parameter callable
            Object sum = futureTask.get(); //The purpose is to get the return value of call()
            System.out.println("The sum is:" + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}

32. Thread creation mode 4: thread pool

Mode 4: use thread pool

The thread pool is really used in development.

1. Frequently create and destroy resources with a large amount of usage, such as concurrency, which has a great impact on performance.

2. The idea is to create many threads in advance, put them into the thread pool, obtain them directly when using them, and return them to the pool after use. It can avoid frequent creation and destruction and realize reuse.

3. Benefits:

  • Improved response speed (reduced thread creation time)
  • Reduce resource consumption (reuse threads in the thread pool without creating them every time)
  • Facilitate thread management (without causing congestion, such as the bus departs once every half an hour)
    • corePoolSize: the size of the core pool
    • maxmumPoolSize: maximum number of threads
    • keepAliveTime: when a thread has no task, how long does it last at most and then it will terminate

Thread pool related API

  • jdk5.0 started to provide thread pool related API s: ExecutorService and Executors
  • ExecutorService: the real thread pool interface. Common subclass ThreadPoolExecutor
    1. void execute(Runnable command): execute the task / command without return value. It is generally used to execute Runnable
    2. Future submit(Callable task): execute a task with a return value. It is generally used to execute Callable tasks
    3. 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
    1. Executors.newCachedThreadPool(): create a thread pool that can create new threads as needed
    2. Executors.newFixedThreadPool(n): create a thread pool with a fixed number of reusable threads
    3. Executors.newSingleThreadExecutor(): create a thread pool with only one thread
    4. Executors. Newscheduledthreadpool (n): creates a thread pool that can schedule commands to run after a given delay or execute periodically
/*
Thread creation mode 4: thread pool
 */
class NumberThread implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

class NumberThread1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (i % 2 != 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

public class ThreadPool {
    public static void main(String[] args) {
        //1. Provide a thread pool with a specified number of threads
        ExecutorService service = Executors.newFixedThreadPool(10);//Object of interface implementation class
        //System.out.println(service.getClass()); // Which class is implemented
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service; //Strong rotation

        //4. Set the properties of thread pool to facilitate thread management
       //service1.setCorePoolSize(15);
       // ...

        //2. To execute the operation of the specified thread, you need to provide an object that implements the Runnable interface or Callable interface implementation class
        service.execute(new NumberThread());   //Suitable for Runnable
        service.execute(new NumberThread1());
        //service.submit();   // Suitable for Callable
        //3. Close the connection pool
        service.shutdown();
    }
}

Topics: Java Multithreading