Multithreaded interview notes sorted by Zhang

Keywords: Java Interview Multithreading

The content may be sloppy, but they are all basic and important things that I think, and they also involve two multi-threaded interview questions

Multithreading

Process process
Thread thread

The program is static

Process is an execution process of a program. It is a dynamic concept. A process will have multiple threads that do not affect each other. The process is allocated by the system

Main () is also called the main thread

The gc () garbage collector is also a thread. The gc thread is provided to us by the jvm, also known as the daemon thread.

A thread is a path that executes independently

In a process, if multiple threads are opened up, the thread scheduling is arranged and executed by the cpu

For the same resource, the problem of resource preemption will occur, and concurrency control needs to be added

Threads bring additional overhead, such as cpu scheduling time and concurrency control overhead

Here is an interview question: the difference between concurrency and parallelism

  1. Concurrency: when multiple threads are operating, if the system has only one cpu, it is impossible for it to execute more than one thread at the same time. It will only divide the cpu running time into several time periods and allocate them. When the thread code of one time period is running, other threads are in a suspended state. This method is called concurrency, Generally speaking, concurrency is not the real simultaneous execution of multiple threads. They can be understood as alternating execution. In the same time period, only one thread is executing, or half of this thread is executing to the next thread. They belong to alternating execution.
  2. Parallelism: it is equivalent to the multi-core situation when a system has more than one cpu. One cpu is executing a thread and the other cpu is also executing a thread. The two threads do not preempt cpu resources and can be carried out at the same time. This method is called parallelism.

Popular understanding:
Concurrency: multiple threads operate on the same object
(explanation: multiple threads operate on the same object. Thread a executes half of the object and does not execute it for the moment. Let thread b execute half of the object and let thread a continue to execute. What I want to express is that multiple threads operate on the same object concurrently. They execute alternately, not synchronously
Parallelism: multiple threads execute simultaneously at the same time
(explanation: multi core CPUs can execute multiple threads at the same time, not alternately, but at the same time

There are three ways to create threads:

  • Inherit Thread class
  • Implement Runnable interface
  • Implement the callable interface
package Demo1;

public class TestThread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("I'm reviewing and looking for a job"+i);
        }
    }

    public static void main(String[] args) {

        TestThread1 t1 = new TestThread1();

        t1.start();

        for (int i = 0; i < 10; i++) {
            System.out.println("I'm making up for it"+i);
        }
    }
}

Here comes another interview question: how to create threads? Thread life cycle and state?

  • Inherit Thread class
  • Implement Runnable interface
  • Implement the callable interface

Initial state: that is, when we new Thread()

Ready state: when the start method is called, the thread immediately enters the ready state, but it does not mean that the execution is scheduled immediately

Blocking state: when calling wait sleep or synchronous locking, the thread enters the blocking state and does not continue to execute until the event is released. The thread enters the ready state again and waits for the cpu to schedule execution

  • Here is an interview question introduced. What will form a blockage

    • Wait blocking: the running thread executes the wait() method, and the JVM will put the thread into the wait pool. (wait will release the held lock)

      Synchronization blocking: when a running thread obtains the synchronization lock of an object, if the synchronization lock is occupied by another thread, the JVM will put the thread into the lock pool.

      Other blocking: when the running thread executes the sleep() or join() method, or makes an I/O request, the JVM will set the thread to the blocking state. When the sleep() state times out, the join() waits for the thread to terminate or time out, or the I/O processing is completed, the thread will return to the ready state.

Running state: enter the running state, and the thread executes the code block of the thread body

Dead state: the thread is interrupted or terminated. Once it enters the dead state, it cannot be started again

The thread is started, not necessarily executed immediately, and is scheduled by the cpu

The Runnable interface uses the static proxy mode

package Demo1;

public class TestThread2 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("RunAble"+i);
        }

    }

    public static void main(String[] args) {
        TestThread2 t2 = new TestThread2();
        Thread thread = new Thread(t2);//Create a thread and put the implementation class that inherits the child Runnable interface into the thread,
                                         //The proxy mode is used
        thread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main"+i);
        }
    }
}


The Runnable interface is recommended because it avoids the limitation of single inheritance and facilitates the use of the same object by multiple threads

package Demo1;

public class TestThread3 implements Runnable{

    private int ticketNums=10;

    @Override
    public void run() {
        while(true){
            if (ticketNums<=0){
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"Got the second"+ticketNums--+"ticket");
        }
    }

    public static void main(String[] args) {
        TestThread3 t3 = new TestThread3();
        new Thread(t3,"Xiao Ming").start();
        new Thread(t3,"Xiao Hong").start();
        new Thread(t3,"Little green").start();
    }
}


Multiple threads operate on the same resource, which is unsafe, data disorder and concurrency problems

Thread.sleep(100); analog delay

Static proxy mode

package Demo1;

public class staticProxy {
    public static void main(String[] args) {
        WeddingCompany weddingCompany = new WeddingCompany(new You());
        weddingCompany.HappyMarry();
    }


}

interface Marry{  //Both proxy and real roles need to implement interfaces
    void HappyMarry();
}

class You implements Marry{//Real role

    @Override
    public void HappyMarry() {
        System.out.println("Miss Zhang learns that Miss Qin is getting married. I'm very happy????");
    }
}

class WeddingCompany implements Marry{ //delegable role

    private Marry target;

    public WeddingCompany(Marry target) {
        this.target = target;
    }

    @Override
    public void HappyMarry() {
        before();
        this.target.HappyMarry();
        after();
    }

    private void after() {
        System.out.println("After marriage, clean up the scene");
    }

    private void before() {
        System.out.println("Before marriage, arrange the scene");
    }


}

Static proxy mode: both the real role and the proxy role need to implement a common interface. The proxy role needs to inject real objects to complete some operations that the real object also wants to implement. The proxy role can also do many ancillary operations. Finally, new a proxy role. Putting the real role into it and implementing the interface to be implemented jointly requires a common interface The same as the implementation method.

Benefits: 1. The agent role can do some things that the real role can't do. 2

2. Real characters can focus more on doing their own things

Definition of functional interface: if only one abstract method is implemented in an interface, it is a functional interface

package Demo02;

public class TestStop implements Runnable{

    private  boolean flag = true;
    @Override
    public void run() {
        int i = 0;
        while (flag){
            System.out.println("run Thread start"+i++);
        }

    }

    public void stop(){
        this.flag=false;
    }

    public static void main(String[] args) {
        TestStop testStop = new TestStop();
        new Thread(testStop).start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if (i==900){
                testStop.stop();
                System.out.println("The thread stopped");
            }
        }
    }
}

The best way to stop the thread is to stop the thread normally, or use the flag bit to set up a flag.

Each object has a lock. sleep will not release the lock, and wait will release the lock

Thread yield is used to suspend the executing thread without blocking, and make the thread change from running state to ready state. In the most important word, yield is not necessarily successful. It depends on cpu scheduling.

Thread queue join ()

There are two statuses in Runnable: ready and Running. Ready means ready for cpu scheduling, and Running means Running and scheduling by cpu

Observe thread state: thread.getState

Thread priority getPriority

  1. Remember that when the priority of a thread is not specified, all threads carry the normal priority.
  2. Priority can be specified in a range from 1 to 10. 10 represents the highest priority, 1 represents the lowest priority, and 5 is the normal priority
  3. Remember that the thread with the highest priority is given priority when executing. However, there is no guarantee that the thread will enter the running state at startup.
  4. The currently running thread may always have a higher priority than the thread waiting to run in the thread pool.
  5. The scheduler determines which thread is executed.
  6. t.setPriority() is used to set the priority of the thread.
  7. Remember that the thread priority should be set before the thread start method is called.
  8. You can use constants such as MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY to set priority.

You can change the priority of the thread through the setPriority method. Remember that the priority of the thread is 1-10. If it exceeds, an exception will be thrown

Threads are divided into user threads and daemon threads

User thread: the virtual machine must ensure that the user thread is executed -- main

Daemon thread: the virtual machine does not have to wait for the daemon thread to finish executing -- gc

Concurrency: for the same object, multiple threads operate at the same time, execute alternately, wait and queue

Parallel: parallel is to assign each task to each processor to complete it independently; At the same time point, tasks must be running at the same time.

This explanation is relatively easy to understand

Thread synchronization security: queues and locks

Because multiple threads of the same process share the same storage space, it brings convenience and access conflict. In order to ensure the correctness of data access, a lock mechanism is added during access. synchronized. When one thread obtains the exclusive lock of the object and monopolizes resources, other threads must wait and release the lock after use

Thread synchronization is bound to lose performance

deadlock

Multiple threads occupy some shared resources and wait for the resources occupied by other threads to run. As a result, two or more threads are waiting for each other to release resources, forming a stop situation, which is prone to deadlock.

More popular: multiple threads hold each other's required resources, and then form a stalemate.

Four necessary conditions for deadlock generation:

  • Mutex condition: a resource can only be used by one thread at a time
  • Request and hold condition: when a process is blocked by requesting resources. Hold on to the resources you have obtained
  • Conditions of non deprivation: the resources obtained by the process cannot be forcibly plundered before they are used
  • Circular waiting condition: a circular waiting resource relationship is formed between several threads.

How to avoid deadlock?
Destroy one of the above conditions

Posted by bivaughn on Sun, 05 Dec 2021 17:15:15 -0800