[Threads and thread creation in the operating system]

Article directory

  • foreword
  • 1. What is a thread
  • 2. Why propose threads
    • 1. Thread context switching
  • 3. The difference between threads and processes
  • Fourth, the state of the thread
  • 5. Common properties of threads
  • Six, create a thread
    • 1. Inherit the Thread class
    • 2. Implement the Runnable interface
    • 3. Anonymous inner class implementation
    • 4. Anonymous inner class creates Runnable subclass object
    • 5. Lambda expressions create Runnable subclass objects
  • Seven, multi-threaded execution display
  • Summarize

Foreword

In the last blog, we learned about processes, so in this blog we will explain threads in the future. For me, I am learning JAVA, so there are many more opportunities to deal with threads than processes (after all For the circle of JAVA, multi-threaded programming is very encouraged), so understanding threads is particularly important

1. What is a thread

A process is the basic unit for the operating system to allocate resources. Therefore, the process is used as the basic unit that can run independently. Until later, a smaller basic unit that can run independently, that is, a thread, was proposed.

2. Why the thread was raised

This will be explained from the process. First of all, we need to know a point of view. The process is a relatively heavyweight multiprocessing system mechanism, and the thread is a lightweight multiprocessing system. The mechanism, where is the heavyweight and lightweight, we can discuss it below
Why is the process heavyweight? This is mainly reflected in resource allocation. Resource allocation is often a very time-consuming operation

And threads are lightweight (we will explain why later), so we encourage multi-threaded programming
The shortcomings of processes for threads are also revealed (although multi-process programming can also solve concurrency problems, it is not recommended)

  1. The cost of creating a process is relatively high
  2. The cost of destroying a process is relatively high
  3. The cost of scheduling a process is relatively high

So the thread was proposed, and the thread is a more lightweight process (lightweight process)
Convention: A process can contain one or more threads
At this time, each of these multiple threads is an independently schedulable execution flow (these execution flows are concurrent)

Here is an explanation of why threads are lightweight: because multiple threads in a process share the system resources of the same process (the process contains threads), which means that for threads, system resources are already Allocated, creating a thread saves the overhead of allocating resources

For example: We have a factory that produces spicy noodles, which are very popular, and the supply is in short supply. There is only one machine for production, as shown in the figure below

At this time, we want to expand and speed up the production of spicy noodles, so we have two ideas
The first (this is the process method)

Let’s rent another yard (apply for allocation of resources), and then get the machine to work (work at the same time)

The second type (this is the thread)

We can use the original resources to open another production line (the cost is reduced). Besides the yard, we can also share other resources, such as raw material storage warehouses, transportation routes, etc.

Small TIP:
1. A thread is not a process. As in the above example, a factory can be called a process, and each assembly line is a thread
2. Thread is the basic unit of CPU scheduling operation
3. Threads also have their own private data, such as stacks and registers, etc.

1. Thread context switching

Regarding thread switching, after all, threads are also scheduled, so when running other threads, thread context switching occurs
There are two cases here, we discuss them separately

1. When two threads do not belong to the same process, the switching process is the same as process context switching;
2. When two threads belong to the same process, because the memory space and the file descriptor table are shared, these resources remain unchanged when switching, and only the private data of the thread, registers and other non-shared data need to be switched ;

3. The difference between thread and process

  1. process contains threads
  2. A process has its own independent memory space and file descriptor table, and multiple threads in the same process share the same memory space and file descriptor table (the process has a complete resource platform, while threads only share essential resources such as registers and stack)
  3. Process is the basic unit of operating system resource allocation, thread is the basic unit of CPU scheduling operation
  4. There is independence between processes. If one process hangs up, it will not affect other processes. However, if one thread hangs up among multiple threads in the same process, the entire process may be taken away.

For the fourth article, an example can be given:
For example, in order to finish eating 100 roast chickens quickly, I called many funny veterans to eat together, but the table is very small, so only a few funny veterans can be on the table at a time, that is, the CPU scheduling thread. At this time, there is a funny As soon as old iron A was on the table, he was pushed down. He was very
So, I flipped the table in a fit of anger, I can’t eat it, everyone don’t want to eat it, oh well, in this way, the whole process is gone.

4. Thread status

//The state of the thread is an enumeration type Thread.State
public class ThreadState {<!-- -->
    public static void main(String[] args) {<!-- -->
        for (Thread.State state : Thread.State.values()) {<!-- -->
            System.out.println(state);
        }
    }
}

  1. NEW: work has been arranged (the thread has not been created), and the action has not yet started (only one Thread)
  2. RUNNABLE: Workable. It can be divided into working and about to start working.
  3. BLOCKED: These all mean waiting in line for other things (indicating the state of waiting for the lock to appear)
  4. WAITING: These all mean waiting in line for other things (the state that appears when using the wait method)
  5. TIMED_WAITING: These all mean waiting in line for other things (waiting at a specified time)
  6. TERMINATED: The job is done (only one Thread)

5. Common properties of threads

6. Create thread

- Thread() // create thread object
- Thread(Runnable target) //Use the Runnable object to create a thread object
- Thread(String name) //Create a thread object and name it
- Thread(Runnable target, String name) //Use the Runnable object to create a thread object and name it

1. Inherit the Thread class

Inherit the Thread class and override the run method

class MyThread extends Thread{<!-- -->
    @Override
    public void run() {<!-- -->
        while (true) {<!-- -->
            System.out.println("hello, thread");
            try {<!-- -->
                Thread. sleep(1000);
            } catch (InterruptedException e) {<!-- -->
                e.printStackTrace();
            }
        }
    }
}
//The most basic thread
public class Demo1 {<!-- -->
    public static void main(String[] args) {<!-- -->
        Thread t = new MyThread();
        t. start();
        while (true) {<!-- -->
            System.out.println("hello,main");
            try {<!-- -->
                Thread. sleep(1000);
            } catch (InterruptedException e) {<!-- -->
                e.printStackTrace();
            }
        }
    }
}

The main method is also a thread, usually called the main thread (two threads are executed alternately (to achieve concurrency))

2. Implement the Runnable interface

class MyRunnable implements Runnable {<!-- -->
    @Override
    public void run() {<!-- -->
        while (true) {<!-- -->
            try {<!-- -->
                Thread. sleep(1000);
            } catch (InterruptedException e) {<!-- -->
                e.printStackTrace();
            }
            System.out.println("hello, thread");
        }
    }
}
//Create a class to implement the runnable interface, instantiate this class and pass it to Thread
public class Demo2 {<!-- -->
    public static void main(String[] args) {<!-- -->
        Thread t = new Thread(new MyRunnable());
        t. start();
    }
}

Compare the above two creation methods (referring to different thread methods)
Inherit the Thread class, use this directly to represent the reference of the current thread object.
Implement the Runnable interface, this represents the reference of MyRunnable. Need to use Thread.currentThread()

3. Anonymous inner class implementation

 public static void main1(String[] args) {<!-- -->
        Thread t1 = new Thread() {<!-- -->
            @Override
            public void run() {<!-- -->
                System.out.println("hello,t1");
            }
        };
        Thread t2 = new Thread() {<!-- -->
            @Override
            public void run() {<!-- -->
                System.out.println("hello,t2");
            }
        };
        t1. start();
        t2.start();
    }

4. Anonymous inner class creates Runnable subclass object

public class Demo4 {<!-- -->
    public static void main(String[] args) {<!-- -->
        Thread t = new Thread(new Runnable() {<!-- -->
            @Override
            public void run() {<!-- -->
                System.out.println("hello");
            }
        });
        t. start();
    }
}

5.lambda expression creates a Runnable subclass object

 public static void main(String[] args) {<!-- -->
        Thread t = new Thread(()-> System.out.println("hello"));
        t. start();
    }

7. Multi-thread execution display

test code

public class Demo5 {<!-- -->
    public static final long count = 100_0000_0000l;
    public static void fun1(){<!-- -->
        long beg = System. currentTimeMillis();
        long a = 0;
        long b = 0;
        for (long i = 0; i < count; i ++ ) {<!-- -->
            a + + ;
        }
        for (long j = 0; j < count; j ++ ) {<!-- -->
            b++;
        }
        long end = System. currentTimeMillis();
        System.out.println("Single thread execution: consumption time" + (end-beg) + "ms");
    }
    public static void fun2() throws InterruptedException {<!-- -->
        long beg = System. currentTimeMillis();
        Thread t = new Thread(new Runnable() {<!-- -->
            @Override
            public void run() {<!-- -->
                long a = 0;
                for (long i = 0; i < count; i ++ ) {<!-- -->
                    a + + ;
                }
            }
        });
        t. start();
        Thread t1 = new Thread(new Runnable() {<!-- -->
            @Override
            public void run() {<!-- -->
                long b = 0;
                for (long i = 0; i < count; i ++ ) {<!-- -->
                    b++;
                }
            }
        });
        t1. start();
        t. join();
        t1. join();
        long end = System. currentTimeMillis();
        System.out.println("Multi-thread execution: consumption time" + (end-beg) + "ms");
    }
    public static void main(String[] args) throws InterruptedException {<!-- -->
        fun1(); //Single thread execution
        fun2(); //Multi-thread execution
    }
}

result

Summary

The above is what I want to talk about today. This article only briefly introduces what a thread is, why it appears, how to understand the context switch of a thread, know the difference between a thread and a process, the 6 states of a thread, common attributes of a thread, and an introduction There are five ways to create threads. For these five methods, I personally recommend the fifth one, because the code is more concise, but you need to have a certain understanding of lambda. That’s all for today. come on! ! !