• What are processes and threads?

Process: A process is the smallest unit of resource allocation in the operating system. A process can have one or more threads. Threads in the same process can share system resources in the process.

Thread: A thread is the smallest unit of CPU scheduling and must depend on the process. Multiple threads in the same process share process data.

For example, a process is like a train, and a thread is a car on the train. Each car on the train has at least one car, and a car on the train can share resources on the train.

  • What are concurrency and parallelism?

Concurrency: Parallel applications can perform different tasks alternately, just as a single CPU core performs multithreaded tasks, not at the same time, but at speeds that are invisible to the naked eye.

Parallelism: Parallelism refers to the ability of an application to perform different tasks at the same time, just as multiple CPU cores perform multithreaded tasks. Two cores can perform different tasks at the same time.

For example:Concurrency means two queues using the same coffee machine can only be used interchangeably, not at the same time. Parallel is two queues using two coffee machines, can be used at the same time, do not interfere with each other.

  • Get into the business

The front said so much is to learn the back of multithreading, but also the interview is easy to ask the point, because a lot of people always do not understand the difference, the following formal entry into multithreading learning.

  • Three ways to create a thread

  • 1. Inherit the Thread class

public class ThreadDemo {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }

    static class MyThread extends Thread {
        @Override
        public void run(a) {
            System.out.println("Thread executed."); }}}Copy the code
  • 2. Implement the Runnable interface

public class ThreadDemo {
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }

    static class MyRunnable implements Runnable{
        @Override
        public void run(a) {
            System.out.println("Thread executed."); }}}Copy the code
  • 3. Implement the Callable interface

public class ThreadDemo {
    public static void main(String[] args) {
        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask<>(myCallable);

        Thread thread = new Thread(futureTask);
        thread.start();

        // Receive the value returned by the thread
        try {
            System.out.println(futureTask.get());
        } catch(Exception e) { e.printStackTrace(); }}static class MyCallable implements Callable<String>{
        @Override
        public String call(a) throws Exception {
            return "Thread executes, I'm the value returned."; }}}Copy the code
  • How do threads stop?

Normally, the thread will be destroyed if it finishes executing, but what if we want to terminate a thread that has been unable to be destroyed due to a time-consuming operation?

  • Method 1 (Stop method)

As you can see, the stop() method is officially deprecated because it forces the termination of a thread and does not guarantee that the thread’s resources will be freed, so it is not recommended.

  • Method two (Custom identifiers)

Since a thread will stop when it completes normal execution, we can define a custom identifier to determine if the status of the identifier changes to stop the task in the thread, and the thread can be destroyed normally. Most people use this method.

public class ThreadDemo {
    private static boolean isRunning = true; // Whether the thread is running
    
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        myThread.start();

        // stop the thread after 2s
        Thread.sleep(2000);
        isRunning = false;
    }

    static class MyThread extends Thread {
        @Override
        public void run(a) {
            while (isRunning) {
                System.out.println("Thread executing"); }}}}Copy the code
  • Method three (Interrupt method) is recommended

Interrupt is very similar to method 2, which requires us to define our own identifier. In fact, we already have one, so we can just use it. Note: Calling the interrupt method does not stop the thread. It is up to us to obtain the state of the interrupt to determine whether the thread continues.

public class ThreadDemo {

    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        myThread.start();

        // stop the thread after 2s
        Thread.sleep(2000);
        myThread.interrupt();
    }

    static class MyThread extends Thread {
        @Override
        public void run(a) {
            while(! Thread.currentThread().isInterrupted()) { System.out.println("Thread executing"); }}}}Copy the code
  • Thread life cycle

Note: The thread calling the start() method does not execute immediately, but enters a ready state waiting for the system to dispatch it.

  • Daemon thread

Threads are divided into user threads and daemon threads, daemon threads will guard all user threads (old dog dog), as long as there are still user threads, daemon threads will not end, when all user threads are finished, daemon threads will automatically end.

public class ThreadDemo {

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        // Set the thread as a daemon thread
        myThread.setDaemon(true);
        myThread.start();
    }

    static class MyThread extends Thread {
        @Override
        public void run(a) {
            while(! Thread.currentThread().isInterrupted()) { System.out.println("Thread executing"); }}}}Copy the code
  • sleep()

Sleep () will make the current calling thread sleep for a period of time, that is, to suspend execution for a period of time, at this time, the CPU execution will be released into the blocking state, waiting for the completion of the blocking state will enter the ready state, waiting for the system scheduling.

  • join()

The join() method suspends all threads except the calling thread, ensuring that the calling thread completes before executing the other threads. If we now create three threads and execute:

public class ThreadDemo {

    public static void main(String[] args) throws InterruptedException {
        MyThread1 myThread1 = new MyThread1();
        MyThread2 myThread2 = new MyThread2();
        MyThread3 myThread3 = new MyThread3();

        myThread1.start();
        myThread2.start();
        myThread3.start();
    }

    static class MyThread1 extends Thread {
        @Override
        public void run(a) {
            for (int i = 0; i < 3; i++) {
                System.out.println("Thread 1 executes ->"+i); }}}static class MyThread2 extends Thread {
        @Override
        public void run(a) {
            for (int i = 0; i < 3; i++) {
                System.out.println("Thread 2 executes ->"+i); }}}static class MyThread3 extends Thread {
        @Override
        public void run(a) {
            for (int i = 0; i < 3; i++) {
                System.out.println("Thread 3 executes ->"+i); }}}}Copy the code

The above code does not join the () code, so the result will be random:

thread1Perform the - >0thread3Perform the - >0thread3Perform the - >1thread2Perform the - >0thread3Perform the - >2thread1Perform the - >1thread1Perform the - >2thread2Perform the - >1thread2Perform the - >2
Copy the code

If we set join() to thread1, we will execute first, and then thread2 and thread3 will continue to grab resources:

MyThread1 myThread1 = new MyThread1();
MyThread2 myThread2 = new MyThread2();
MyThread3 myThread3 = newMyThread3(); myThread1.start(); myThread1.join(); myThread2.start(); myThread3.start(); Execution result: threads1Perform the - >0thread1Perform the - >1thread1Perform the - >2thread2Perform the - >0thread3Perform the - >0thread2Perform the - >1thread3Perform the - >1thread2Perform the - >2thread3Perform the - >2
Copy the code
  • yield()

The yield() method causes the current thread to change from a running state to a ready state. At this point, the CPU will randomly schedule the ready thread, either to this thread or to another thread, so the yield() method may yield resources and immediately rob them again.

  • Wait () and notify() and notifyAll()

These three methods are all methods of the Object class, so all objects can call these three methods. Since these three methods are related to the locking mechanism, this article does not cover the concept of thread locking, so we will explain the locking mechanism in detail in the next part.