Roommate hit the king and learned Java multithreading..

Posted by Mel on Thu, 16 Dec 2021 16:38:53 +0100

For Java beginners, many concepts of multithreading sound difficult to understand. For example:

  • Process is the encapsulation of runtime program, the basic unit of resource scheduling and allocation, and realizes the concurrency of operating system.
  • Thread is the subtask of the process, the basic unit of CPU scheduling and dispatching, and realizes the concurrency within the process.

It's abstract, isn't it? To make an analogy, you are beating a king (actually I can't play ha doge):

  • The process can be compared to the game you played
  • Threads can be compared to heroes of your choice or crystal monsters in the game.

With this metaphor to understand the relationship between processes and threads, a process can have multiple threads, which is called multithreading. Does it feel very understandable?

❤ 1. Thread under process

(individual hero characters, wild monsters and small soldiers can't run)

❤ 2. Processes will not affect each other. The end of the main thread will lead to the end of the whole process

(there will be no connection and influence between the two games. Your crystal will be pushed away and your game will be over)

❤ 3. Different process data is difficult to share

(it's hard to connect the two games. For example, the enemy of Shangba matches again)

❤ 4. Data can be easily shared between different threads in the same process

(in the game you play, you can see the status of each player - life and death, and the appearance of each player, etc.)

❤ 5. The memory address used by the process can limit the usage

(the open room mode determines how many people you can set to enter. When the room is full, others can't enter unless someone leaves the room)

After understanding the above concepts, let's take a look at two ways of multithreading:

♠ ① : create a class, inherit the Thread class, and override the run method.

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ":Yes" + i + "A little soldier");
        }
    }
}

Let's write a test method to verify the following:

//Create MyThread object
MyThread t1=new  MyThread();
MyThread t2=new  MyThread();
MyThread t3=new  MyThread();
//Set the name of the thread
t1.setName("Luban");
t2.setName("Liu Bei");
t3.setName("Arthur");
//Start thread
t1.start();
t2.start();
t3.start();

Let's take a look at the results after implementation:

♠ ② : create a class to implement the Runnable interface and override the run method.

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {//An exception will occur in sleep, which needs to be displayed for processing
                Thread.sleep(20);//Pause for 20 milliseconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "Yes:" + i + "A little soldier");
        }
    }
}

Let's write a test method to verify the following:

//Create MyRunnable class
MyRunnable mr = new MyRunnable();
//Create a parameterized construct of the Thread class and set the Thread name
Thread t1 = new Thread(mr, "Fei Zhang");
Thread t2 = new Thread(mr, "army officer's hat ornaments");
Thread t3 = new Thread(mr, "Lv Bu");
//Start thread
t1.start();
t2.start();
t3.start();

Let's take a look at the results after implementation:

❤ 1. Why override the run method?

Because the run method is used to encapsulate the code executed by the thread.

❤ 2. What is the difference between the run() method and the start() method?

  • run(): encapsulates the code executed by the thread. Calling directly is equivalent to calling ordinary methods.
  • start(): starts the thread, and then the JVM calls the run() method of the thread.

❤ 3. Which is better to create multiple threads by inheriting the method of Thread and implementing the Runnable interface?

The implementation of the Runable interface is good for two reasons:

  • ♠ ① , avoiding the limitation of Java single inheritance
  • ♠ ② It is suitable for multiple same program codes to deal with the same resource, and effectively separate threads, code and data, which is more in line with the object-oriented design idea.

For thread control, you will encounter three common methods. Let's introduce them one by one.

1) sleep(): pauses the currently executing thread for a specified number of milliseconds, that is, it enters the sleep state.

It should be noted that exceptions should be handled during sleep.

try {//An exception will occur in sleep, which needs to be displayed for processing
    Thread.sleep(20);//Pause for 20 milliseconds
} catch (InterruptedException e) {
    e.printStackTrace();
}

2) join(): wait for this thread to finish executing, then it's the next thread's turn to get the cpu's execution right. If you use this, you also have to throw an exception.

//Create MyRunnable class
MyRunnable mr = new MyRunnable();
//Create a parameterized construct of the Thread class and set the Thread name
Thread t1 = new Thread(mr, "Fei Zhang");
Thread t2 = new Thread(mr, "army officer's hat ornaments");
Thread t3 = new Thread(mr, "Lv Bu");
//Start thread
t1.start();
try {
    t1.join(); //Wait for t1 to execute before t2 and t3 grab
} catch (InterruptedException e) {
    e.printStackTrace();
}
t2.start();
t3.start();

Let's take a look at the results after implementation:

3) setDaemon(): mark this thread as a daemon thread. To be exact, it serves other threads, such as the garbage collection thread in Java, which is a typical daemon thread.

//Create MyRunnable class
MyRunnable mr = new MyRunnable();
//Create a parameterized construct of the Thread class and set the Thread name
Thread t1 = new Thread(mr, "Fei Zhang");
Thread t2 = new Thread(mr, "army officer's hat ornaments");
Thread t3 = new Thread(mr, "Lv Bu");

t1.setDaemon(true);
t2.setDaemon(true);

//Start thread
t1.start();
t2.start();
t3.start();

If other threads are executed and the main method (main thread) is executed, the JVM will exit, that is, stop running. If the JVM stops running, the daemon thread will naturally stop.

Finally, let's take a look at the life cycle of threads. A picture is worth a thousand words.

The creativity and most of the content of this article come from iron powder for a long time. It's very interesting, ha ha. The second brother has made some adjustments, hoping to give a little help and inspiration to his buddies who are beginning to learn Java multithreading.

By the way, this article has been included in the "concurrent programming" column of the advanced path of Java programmers, which has won 832 stars on GitHub:

https://github.com/itwanger/toBeBetterJavaer

I hope more and more Java lovers can benefit from this open source project, and more and more people's star will encourage me to create better content~