Java learning path: day18 multithreading

Keywords: Windows Java jvm github

Article catalog

All source code: https://github.com/name365/JavaSE-30Day

Reprinted from atguigu.com video

Chapter 8 multithreading

Basic concepts: program, process, thread

  • A program is a set of instructions written in a certain language to complete a specific task. That is, a static code, a static object.
  • A process is an execution of a program, or a running program. It is a dynamic process: it has its own process of production, existence and extinction. ——Life cycle
    • For example: QQ in operation, MP3 player in operation, the program is static and the process is dynamic
    • As a unit of resource allocation, the system allocates different memory areas to each process at runtime
  • Thread, the process can be further refined into thread, is a program internal execution path.
    • If a process executes multiple threads in parallel at the same time, it supports multithreading
    • As the unit of scheduling and execution, each thread has its own running stack and program counter (pc). The cost of thread switching is small
    • Multiple threads in a process share the same memory unit / memory address space - "they allocate objects from the same heap and can access the same variables and objects. This makes communication between threads easier and more efficient. However, system resources shared by multiple threads may bring security risks.

Processes and threads

  • Understanding of single core CPU and multi-core CPU
    • Single core CPU is actually a kind of fake multithreading, because only one thread can be executed in a time unit. For example: Although there are multiple lanes, there is only one staff member charging at the toll station, and only after charging can the toll pass through, so the CPU is like a toll collector. If someone doesn't want to pay, the toll collector can hang him (hang him up, wait for him to figure it out, prepare the money, and then charge). But because the CPU time unit is very short, it can't be felt.
    • If it is multi-core, it can better play the efficiency of multi-threaded. (today's servers are multi-core)
    • In fact, a Java application java.exe has at least three threads: main() main thread, gc() garbage collection thread and exception handling thread. Of course, if an exception occurs, it will affect the main thread.
  • Parallel and concurrent
    • Parallel: multiple CPU s perform multiple tasks at the same time. For example: many people do different things at the same time.
    • Concurrency: one CPU (time slice) executes multiple tasks at the same time. For example: second kill, multiple people do the same thing.

Advantages of using multithreading

Background: taking a single core CPU as an example, it takes less time to complete multiple tasks (call multiple methods) by using only a single thread than by using multiple threads. Why do you still need multiple threads?

  • Advantages of multithreaded programs:
    1. Improve application response. It is more meaningful for the graphical interface and can enhance the user experience.
    2. Improve CPU utilization of computer system
    3. Improve the program structure. Divide the long and complex process into multiple threads, run independently, and facilitate understanding and modification

When multithreading is needed

  • The program needs to perform two or more tasks at the same time.
  • The program needs to implement some tasks to wait, such as user input, file read-write operation, network operation, search, etc.
  • When you need some programs running in the background.

Creation and use of threads

Thread creation and startup

  • The Java language JVM allows programs to run multiple threads, which is embodied by the java.lang.Thread class.
  • Properties of Thread class
    • Each Thread is operated by the run() method of a specific Thread object. The main body of the run() method is often called the Thread body
    • Start the Thread through the start() method of the Thread object instead of calling run() directly

Thread class

  • Thread(): create a new thread object
  • Thread(String threadname): creates a thread and specifies the thread instance name
  • Thread(Runnabletarget): Specifies the target object to create a thread, which implements the run method in the Runnable interface
  • Thread(Runnable target, String name): create a new thread object

Two ways to create threads in API

  • There are two ways to create a new execution thread before JDK 1.5:
    • How to inherit Thread class
    • How to implement the Runnable interface

One way to create multithreading: inherit Thread class

/**
 * Creation of multithreading: inherited from Thread class
 * 1.Create a subclass that inherits from the Thread class
 * 2.Override the run() method of Thread -- > declare the method of this Thread in run()
 * 3.Create sub object of Thread class
 * 4.Call start() from this object
 *
 * Example: traverse all even numbers within 100
 *
 * @author subei
 * @create 2020-05-07 15:28
 */

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

public class ThreadTest {
    public static void main(String[] args) {
        //3. Create sub object of Thread class
        MyThread t1 = new MyThread();

        //4. Call start() through this object: ① start the current thread ② call the run() of the current thread
        t1.start();

        //The following operations are still performed in the main thread
        for(int i = 1;i < 100;i++){
            if(i % 2 == 0){
                System.out.println(i + "***main()***");
            }
        }
    }
}
  • The process of creating and starting mt sub thread


Two problems in the process of creation

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

public class ThreadTest {
    public static void main(String[] args) {
        //3. Create sub object of Thread class
        MyThread t1 = new MyThread();

        //4. Call start() through this object: ① start the current thread ② call the run() of the current thread
        t1.start();
        //Problem 1: we can't start a thread by calling run() directly.
//        t1.run();

        //Problem 2: start another thread to traverse an even number within 100. You can't also let the thread that has already started () execute. IllegalThreadStateException will be reported
//        t1.start();
        //We need to recreate the object that created a thread and go to start()
        MyThread t2 = new MyThread();
        t2.start();

        //The following operations are still performed in the main thread
        for(int i = 1;i < 100;i++){
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i + "***main()***");
            }
        }
    }
}

Exercise 1

  • Style 1
/**
 * Exercise: create two sub threads, one traversing an even number within 100, and the other traversing an odd number within 100
 *
 *
 * @author subei
 * @create 2020-05-07 16:34
 */
public class ThreadDemo {
    public static void main(String[] args) {
        MyThread m1 = new MyThread();
        m1.start();

        MyThread2 m2 = new MyThread2();
        m2.start();
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        for(int i = 0;i < 100;i++){
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}
class MyThread2 extends Thread{
    @Override
    public void run() {
        for(int i = 0;i < 100;i++){
            if(i % 2 != 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}
  • Writing method 2
/**
 * Exercise: create two sub threads, one traversing an even number within 100, and the other traversing an odd number within 100
 *
 *
 * @author subei
 * @create 2020-05-07 16:34
 */
public class ThreadDemo {
    public static void main(String[] args) {

        //How to create an anonymous subclass of Thread class
        new Thread(){
            @Override
            public void run() {
                for(int i = 0;i < 100;i++){
                    if(i % 2 == 0){
                        System.out.println(Thread.currentThread().getName() + ":" + i);
                    }
                }
            }
        }.start();

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

Methods of Thread class

/**
 * Common methods of testing Thread class
 * 1.start():Start the current thread and execute the run()
 * 2.run():It is usually necessary to override this method in the Thread class and declare the operation to be performed by the created Thread in this method
 * 3.currentThread(): Static method, return the thread of current code execution
 * 4.getName():Get the name of the current thread
 * 5.setName():Set the name of the current thread
 * 6.yield():Release the execution right of the current CPU
 * 7.join():In thread a, call join() of thread b. At this point, thread a will enter the blocking state until thread b is fully executed, and then thread a will be.
 *          End blocking state.
 * 8.stop():Out of date. When this method is executed, forces the end of the current thread.
 * 9.sleep(long millitime): Lets the current thread "sleep" in milliseconds for the specified time. Within the specified millisecond time,
 *                          The current thread is blocked.
 * 10.isAlive(): Return to boolean to determine whether the thread is still alive
 *
 * @author subei
 * @create 2020-05-07 16:51
 */

class HelloThread extends Thread{
    @Override
    public void run() {
        for(int i = 0;i < 100; i++){

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

            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
//            if(i % 20 == 0){
//                yield();
//            }
        }
    }

    public HelloThread(String name){
        super(name);
    }
}

public class ThreadModeTest {
    public static void main(String[] args) {
        HelloThread h1 = new HelloThread("Thread : 1");

//        h1.setName("thread one");

        h1.start();

        //Name the main thread
        Thread.currentThread().setName("Main thread");

        for(int i = 0;i < 100; i++){
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }

            if(i == 20){
                try {
                    h1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        System.out.println(h1.isAlive());
    }
}

Scheduling of threads

  • scheduling strategy

    • Time slice

    • Preemptive: high priority threads preempt CPU

  • Java scheduling method

    • Threads of the same priority form a first in, first out queue (first in, first out service), using a time slice strategy
    • For high priority, use preemptive strategy of priority scheduling

thread priority

/**
 * - Priority level of thread
 *   - MAX_PRIORITY: 10
 *   - MIN _PRIORITY: 1
 *   - NORM_PRIORITY: 5 --->Default Priority 
 * - Methods involved
 *   - getPriority() : Return thread priority
 *   - setPriority(intnewPriority) : Change thread priority
 *
 *   Note: the high priority thread should preempt the execution power of the low priority thread cpu.
 *       But only in terms of probability, high priority threads are executed with high probability.
 *       It doesn't mean that the low priority thread will be executed only after the high priority thread is executed.
 *
 *
 * @author subei
 * @create 2020-05-07 17:47
 */

class HelloThread extends Thread {
    @Override
    public void run() {
        for (int j = 0; j < 100; j++) {

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

            if (j % 2 == 0) {
                System.out.println(getName() + ":" + getPriority() + ":" + j);
            }
        }
    }
    public HelloThread(String name){
        super(name);
    }
}

public class ThreadModeTest {
    public static void main(String[] args) {
        HelloThread h2 = new HelloThread("Thread : 1");
        h2.start();

        //Set priority of subthreads
        h2.setPriority(Thread.MAX_PRIORITY);

        //Name the main thread
        Thread.currentThread().setName("Main thread");
        Thread.currentThread().setPriority((Thread.MIN_PRIORITY));

        for(int j = 0;j < 100; j++){
            if(j % 2 == 0){
                System.out.println(Thread.currentThread().getName() + ":" + Thread.currentThread().getPriority() + ":" + j);
            }

//            if(j == 20){
//                try {
//                    h2.join();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
        }

        System.out.println(h2.isAlive());
    }
}

Exercise 2

  • Multi window ticket selling
/**
 * Example: create three c windows to sell tickets. The total number of tickets is 100
 *
 * There is a thread safety problem to be solved.
 *
 * @author subei
 * @create 2020-05-07 18:21
 */

class Windows extends Thread{

    private static int ticket = 100;

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

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

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

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

Exercise 3

/**
 * Example: create three c windows to sell tickets. The total number of tickets is 100
 *
 * There is a thread safety problem to be solved.
 *
 * @author subei
 * @create 2020-05-07 18:21
 */

class Windows extends Thread{

    private static int ticket = 100;

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

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

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

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

The second way to create multithreading: to implement the Runnable interface

/**
 * The second way to create multithreading: to implement the Runnable interface
 * 1.Create a class that implements the Runnable interface
 * 2.Implementation class to implement the abstract method in Runnable: run()
 * 3.Creating objects to implement classes
 * 4.Pass this object as a parameter to the constructor of the Thread class to create an object of the Thread class
 * 5.Call start() through the object of Thread class
 *
 *
 * @author subei
 * @create 2020-05-07 18:39
 */
//1. Create a class that implements the Runnable interface
class MThread implements Runnable{

    //2. Implementation 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 ThreadTest1 {
    public static void main(String[] args) {
        //3. Create the object of the implementation class
        MThread m1 = new MThread();
        //4. Pass this object as a parameter to the constructor of Thread class, and create the object of Thread class
        Thread t1 = new Thread(m1);
        //5. call start() through the object of the Thread class: ① start the thread; ② call the run() of the current thread -- > call the run() of the target of the Runnable type
        t1.start();

        //Start another thread to traverse even numbers within 100
        Thread t2 = new Thread(m1);
        t2.setName("Thread 2");
        t2.start();
    }
}

The relation and difference between inheritance and Realization

/**
 *Compare the two ways to create threads.
 *In development: priority: the way to implement the Runnable interface
 *Reasons: 1. There is no limitation of class single inheritance in the way of implementation
 *2. The implementation method is more suitable to deal with the situation that multiple threads have shared data.
 *  
 *Contact: public class Thread implements Runnable
 *The same thing: both methods need to override run (), which declares the logic that the thread will execute in run().
 *
 * @author subei
 * @create 2020-05-07 18:39
 */

Supplement: classification of threads

  • There are two kinds of threads in Java: one is the guard thread, the other is the user thread.

    They are the same in almost every respect, the only difference being to determine when the JVM leaves.

    Daemon threads are used to serve user threads. By calling **thread.setDaemon(true) * before the start() method, a user thread can turn a daemon thread into a daemon thread.

    Java garbage collection is a typical guard thread.

    If there are all daemons in the JVM, the current JVM will exit.

    Image understanding: rabbit, dog, bird and bow

    The whole Java stack series is my own notes. Writing is not easy. If you can, please give me a compliment! A kind of

66 original articles praised 261 visits 50000+
follow private letter

Posted by igorek on Sun, 17 May 2020 18:31:19 -0700