Summary of Java multithreading Basics

1 concurrency and parallelism

Parallelism: multiple instructions are executed simultaneously on multiple CPUs at the same time.

Concurrency: at the same time, multiple instructions are executed alternately on a single cpu.

2 process and thread

Process: a running program.

Independence: a process is not only a basic unit that can run independently, but also an independent unit for system resource allocation and scheduling.

Dynamic: the essence of a process is an execution process of a program. A process is produced and dies dynamically.

Concurrency: any process can execute concurrently with other processes.

Thread: it is a single sequential control flow in a process and an execution path.

Single thread: a process with only one execution path is called a single threaded program.

Multithreading: if a process has multiple execution paths, it is called a multithreaded program.

3 method of realizing multithreading

3.1 method 1: inherit Thread class

(1) Introduce thread class

thread extends Object

thread implements Runnable

Construction method of Thread

Tread(Runnable target)

Tread(Runnable target,String name)

(2) Specific steps: create a class to inherit the Thread class. This subclass overrides the run () method in the Thread, and then allocate and start the instance of the subclass.

public class Demo1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(i);
        }
    }
}

public class Test01 {
    public static void main(String[] args) {
        Demo1 d1 =new Demo1();
        Demo1 d2 =new Demo1();
        d1.start();
        d2.start();
    }
}

☆ why rewrite the run () method?

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

☆ what is the difference between the run() method and the start () method?

run (): encapsulates the code executed by the thread. It is called directly, which is equivalent to the call of ordinary methods.

start (): starts the thread, and then the jvm calls the run () method of the thread.

3.2 mode 2: implement Runnable interface

(1) Specific steps: declare a class that implements the Runnable interface, and then implement the run method. Then, you can allocate an instance of the class, pass it as a parameter when creating the Thread object, and start it.

(2) Construction method of thread

Tread(Runnable target)

Tread(Runnable target,String name)

public class Demo2 implements Runnable{
@Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            //The getName method cannot be used directly because Demo2 implements the Runnable interface.
            //Thread method is not inherited.
            //You can get the thread currently executing by.
            System.out.println(Thread.currentThread().getName()+":"+i);
        }        
    }
}

public class Test2 {
    public static void main(String[] args) {
        Demo2 d1 =new Demo2();      
        Thread t1 = new Thread(d1,"train");
        Thread t2 = new Thread(d1,"automobile");        
        t1.start();
        t2.start();
    }
}

3.3 mode 3: implement Callable interface

(1) Specific steps: first, write a class that implements the Callable interface. Create a new object of this class in the main method, then register the generated instance object in the FutureTask class, and then register the instance of FutureTask class into Thread for running. Finally, you can use the get method in FutureTask < V > to obtain the return value of the custom Thread.

(2) Principle: we can check the source code of the Callable interface and find that there is only one definition of the call () method Futuretask < V > implements the interface of runnablefuture < V >, and this runnablefuture < V > interface also implements the interface of Runnable. Futuretask < V > also has a constructor that needs to pass in Callable < V > type parameters, and will be assigned to the private attribute of futuretask < V >. No matter how we implement multithreading, we need to call the Start () method in the tree class to request io, cpu and other resources from the operating system. A Runnable interface parameter needs to be passed in the tree parameter structure, and the instance of futuretask < V > can be used as this parameter to pass in to the tree.

ps:get() method is a method in futureask < V > class, and it may be necessary to throw exceptions when using it.

public class Demo3 implements Callable {
    @Override
    public Object call() throws Exception {
        for (int i = 0; i <10 ; i++) {
            System.out.println("Multithreading mode 3 "+i);
        }
        return "It's over";
    }
}


public class Test03 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Demo3 d =new Demo3();
        FutureTask<String> ft =new FutureTask<>(d);
        Thread t1 =new Thread(ft);
        t1.start();
        String s = ft.get();
        System.out.println(s);
    }
}

4 set and get the name of the thread

Two methods are provided in the tree class to set and get the thread name

void setName(String name) changes the name of this thread to be equal to the name of the parameter

String getName() returns the name of this thread

Thread currentThread() returns an object for the thread currently executing

ps: if the getName method in the Tread class is invoked in the output of the Demo4 class and is not named in Test04, the system will give a name according to its source code, for example, "Demo-0:0 or Demo-1: 0".

public class Demo4 extends Thread{
    public Demo4() {
    }
    public Demo4(String name) {
        super(name);
    }
    @Override
    public void run() {
        for (int i= 0; i <5; i++) {
            System.out.println(getName()+":"+i);
        }
    }
}

public class Test04 {
    public static void main(String[] args) {
        //Naming method 1: call parameterized construction
        Demo4 d1 =new Demo4("aircraft");
        Demo4 d2 =new Demo4("high-speed rail");
       /*Naming method 2: call parameterless construction
        Demo4 d1 =new Demo4();
        Demo4 d2 =new Demo4();
        d1.setName("Aircraft ");
        d2.setName("High speed railway (HSR) ";
       */
        d1.start();   d2.start();
    }
    }

5 common control methods of threads

static void sleep(long millis) causes the currently executing thread to stay (pause execution) for a specified number of milliseconds.

void join () waits for the thread to die

Void setDaemon (boolean on) marks this thread as a daemon. When all running threads are daemon threads,

The Java virtual machine will exit

5.1 thread hibernation

static void sleep(long millis) stops (pauses) the currently executing thread for the specified number of milliseconds.

public class Demo5 extends Thread{                  Operation results
    public Demo5() {                                Liu Bei+0
    }                                               Sun Quan+0
    public Demo5(String name) {                     Cao Cao+0
        super(name);                                Sun Quan+1
    }                                               Liu Bei+1
    @Override                                       Cao Cao+1
    public void run() {                             Sun Quan+2
        for (int i = 0; i < 5; i++) {               Cao Cao+2
       /*Tread Indicates that the currently running thread stays for 1000 milliseconds.*/    Liu Bei+2
            try {                                     *
                Thread.sleep(1000);                   * 
            } catch (InterruptedException e) {        *
                e.printStackTrace();
            }
            System.out.println(getName()+"+"+i);
        }
    }
}


public class Test5 {
    public static void main(String[] args) {
        Demo5 d1 =new Demo5("Cao Cao");
        Demo5 d2 =new Demo5("Liu Bei");
        Demo5 d3 =new Demo5("Sun Quan");
        d1.start();
        d2.start();
        d3.start();
    }
}

Conclusion: these three people are also grabbing the right to use cpu when executing.

5.2 thread death

void join() will execute other threads only after the thread has finished executing.

public class Demo5 extends Thread{
    public Demo5() {
    }
    public Demo5(String name) {
        super(name);
    }
    @Override
    public void run() {
        for (int i= 0; i <5; i++) {
            System.out.println(getName()+":"+i);
        }
    }
}
public class Test5 {
    public static void main(String[] args) throws InterruptedException {
        Demo5 d1 =new Demo5("Emperor");
        Demo5 d2 =new Demo5("The elder prince in the Qing Dynasty");
        Demo5 d3 =new Demo5("Two elder brothers");
        d1.start();
        d1.join();
        //Only after the emperor's execution can the two elder brothers have the opportunity to execute.
        d2.start();
        d3.start();
    }
}

5.3 daemon thread

Void setDaemon (boolean on) marks this thread as a daemon. When all running threads are daemon threads,

The Java virtual machine will exit (not immediately, will struggle for a while)

public class Demo5 extends Thread{
    public Demo5() {
    }
    public Demo5(String name) {
        super(name);
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"+"+i);
        }
    }
}

public class Test5 {
    public static void main(String[] args)  {
        Demo5 d1 =new Demo5("Emperor");
        Demo5 d2 =new Demo5("The elder prince in the Qing Dynasty");
        Demo5 d3 =new Demo5("Two elder brothers");
        d3.setDaemon(true);
        d2.setDaemon(true);
        d1.start();
        d2.start();
        d3.start();
    }
}

6 thread scheduling

6.1 thread scheduling mode:

(1) Time sharing scheduling model: all threads use the right to use cpu in turn, and evenly allocate the time slice of cpu occupied by each thread

(2) Preemptive scheduling model: give priority to the threads with high priority to use cpu. If the threads have the same priority, one will be selected randomly. The threads with high priority will obtain more cpu time slices.

Java uses a preemptive scheduling model.

6.2 methods to get and set priority in the tree class

ps: the high priority of a thread only means that the thread has a high probability of obtaining cpu time slices, but you can only see the effect you want when it is run more or more times.

final int getPriority() returns the priority of this thread

final void setPriority(int newPriority) change the priority of this thread. The default priority of the thread is 5; Thread priority ranges from 1 to 10

public class Demo6 implements Callable {
    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 1000; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
        }
        return "Program complete";
    }
}

public class Test06 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Demo6 d1 =new Demo6();
        FutureTask<String> ft =new FutureTask<>(d1);
        Thread t1 =new Thread(ft);
        t1.setName("aircraft");
        t1.setPriority(9);
        t1.start();
        Demo6 d2 =new Demo6();
        FutureTask<String> ft2 =new FutureTask<>(d2);
        Thread t2 =new Thread(ft2);
        t2.setName("high-speed rail");
        t2.setPriority(1);
        t2.start();
        System.out.println(t1.getPriority());
         String s = ft2.get();
        System.out.println(s);
    }
}

7 Summary of three ways to realize multithreading

(1) Implementation of Runnable and Callable interfaces

Advantages: strong expansibility. You can inherit other classes while implementing this interface, and the call method of the Callable interface will also have a return value

Disadvantages: the code is complex and the methods in the Thread class cannot be used directly

(2) Inherit Thread class

Benefits: the code is simple and you can directly use the methods in the Thread class

Disadvantages: poor expansibility, unable to inherit other classes.

Keywords: Java Back-end

Added by perezf on Mon, 24 Jan 2022 23:01:17 +0200