A deer can follow a sheep when its heart and body follow a sheep when its heart leads

multithreading


  1. Basic concepts: program, process, thread
  2. Create and use (two types)
  3. The life cycle of a thread
  4. Synchronization of threads (there are three ways to solve thread-safety problems)
  5. Thread communication
  6. New thread creation methods in JDK5.0

The basic concept

Program: A composition of static code written in a language to accomplish a task

Process: a program that is running, that is, loaded into memory. A process has a method area and a heap

Thread: The path of execution within a program. a process usually has multiple threads. A thread has a virtual stack and a program counter, that is, threads under the process share the process’s method area and heap area, and each thread has its own virtual stack and program counter (PC) (extension: JVM tuning means tuning this shared part).

Parallel: Multiple cpus perform multiple tasks simultaneously

Concurrency: a CPU performs multiple tasks “simultaneously” (using time slices), such as seckilling or multiple people doing the same thing

Multithreading benefits: improved program responsiveness (more meaningful for graphical interfaces, improved user experience), improved CPU utilization, improved program structure, easy to understand and modify

Multithreaded scenarios: programs need to execute two or more tasks at the same time, need to implement some waiting tasks (file read and write, network operation, search, etc.), need some background running programs

Create and use

Commonly used method

  • void start()Function:

A. Start the current thread b. Call the run() method of the current thread: Start () can only be called once on the same thread, and the run() method cannot be used to start the thread directly (run() is still in the main thread, the target thread is not started). If the method name is not used later, anonymous subclasses can be used to start the thread

  • run(): Operations performed by a thread when it is scheduled
  • void setName(): sets the name of the Thread (Thread has a constructor that can also be named)
  • String getName(): Returns the name of the thread
  • static Thread currentThread(): Returns the current thread. If it is this in the Thread subclass, it is usually used in the main Thread and Runnable implementation classes
  • static void yield(): Thread concession

A. Release the execution right of the CPU and transfer the execution opportunity to the thread with the same priority or higher. After release, the same thread may seize the execution right next time. B. If no thread of the same priority exists in the queue, ignore this method

  • join(): When a join() method of another thread is called in a program execution stream, the calling thread is blocked until the join thread joined by the join() method executes. Low-priority threads can also be executed
  • static void sleep(long millis): Specifies the time in milliseconds

A. Make the current active thread give up CPU control (sleep, during millis time, the current thread is blocked) in a specified period of time, so that other threads have a chance to be executed, and queue up again when the time is up b. InterruptedException is thrown

  • stop(): Force the thread lifecycle to end, not recommended (method obsolete)
  • boolean isAlive: Determines whether the thread is alive

Scheduling of threads

Scheduling strategy: time slice, preemption (high-priority threads seize CPU)

Java scheduling method:

  1. Processes of the same priority form a first-in, first-out queue (first-come, first-served) and use a time slice policy
  2. For high priorities, preemptive scheduling is used

Priority levels of threads: MAX_PRIORITY: 10 (maximum priority) MIN_PRIORITY: 1 (minimum priority) NORM_PRIORITY: 5 (default priority)

Involved methods: getPriority() : returns the priority of the thread. SetPriority (int newPriority) : changes the priority of the thread

Note: thread creation inherits the parent thread’s priority priority is only for probability, low priority is only the probability of getting a schedule, not necessarily after the high priority thread is called.

Method 1: Inherit Thread

  1. Create a subclass that extends from Thread
  2. Override Thread’s run() to write what you want the Thread to do in the run() method
  3. Create a subclass object of Thread
  4. Call start() with this object

Method 2: Implement the Runnable interface

  1. Create a class that implements the Runnable interface
  2. Implementation classes to implement abstract methods of the Runnable class: run()
  3. Create an object that implements the class
  4. Pass this object as an argument to the constructor of The Thread class to create an object of the Thread class
  5. Call the start() method from the Thread object

Method one, two contrast

The Runnable interface is preferred for development reasons:

  1. The implementation does not have the limitations of single inheritance of a class
  2. The implementation is better suited to situations where multiple threads have shared data

Contact:

  1. The Thread class itself implements the Runnable interface
  2. Either way, you override the run() method to write the logic that the thread is implementing in the run() method

The life cycle of a thread

The Thread.State class defines several states of threads

  • New: When an object of the Thread class or its subclass is declared to be created, the newly created Thread object is in the new state (i.e., when new)
  • Ready: after a thread is started (), it will enter the thread queue to wait for the CPU time slice. At this point, it is ready to run, but it is not allocated CPU resources in the state
  • Run: When a ready thread is scheduled and CPU resources are acquired, it enters the run state. The run() method defines the actions and functions of the thread
  • Blocking: In a special case, when an input/output operation is manually suspended or executed, the CPU is relinquish and its execution is temporarily suspended
  • Death: a thread completes all of its work or is terminated prematurely by mandatory termination or other exception

Thread communication

  • Common communication methods (the following three methods are defined in Object) :

Wait (), notify(), and notifyAll()

  • Thread classification:
  1. Daemon threads (e.g. Java gc garbage collection threads)
  2. User threads (e.g. Java main() main thread)
  • Daemons are used to service user threads by calling them before start(),thread.setDaemon(true)You can turn a user thread into a daemon thread. Java garbage is a typical daemon thread. If the JVM is full of daemon threads, the current JVM will exit.
  • Similarities and differences between sleep() and wait()

Same: once the method is executed, both can cause the current thread to enter the blocking state:

  1. The Thread class declares sleep() and the Object class declares wait().
  2. The call requirements vary; sleep() can be called in any scenario, and wait() must be called in a synchronized method or block of synchronized code
  3. As for whether to release the synchronization monitor, sleep() does not release the synchronization monitor, and wait() does if both methods are used in synchronized code blocks or synchronized methods

Synchronization of threads (to address thread safety issues)

concept

  • The instability of the execution result caused by the uncertainty of the execution of multiple threads

  • The sharing of multiple thread variables can result in incomplete operation results and destroy data

  • Method 1: Synchronize code blocks

Synchronized {// Code that needs to be synchronized}Copy the code
  1. Note: Code that operates on shared data, i.e. code that needs to be synchronized (can’t contain more code, can’t contain less code)
  2. Shared data: a variable operated by multiple threads, such as ticket in the example
  3. Synchronization monitor: commonly known as lock (any object of a class can act as a synchronization monitor, i.e. lock)
  4. Synchronization monitor requirements: Multiple threads must use the same lock together, and the lock must be unique.
  5. Add: You can consider using this as a synchronization monitor (with caution when inheriting Thread, or consider using the current class as a synchronization monitor)
  • Method 2: Synchronization method

Note: If the code that operates on shared data is completely declared in a method, we might as well use the synchronous generation method to solve thread safety problems

  1. The synchronization monitor used by non-static synchronization methods is this
  2. The synchronization monitor used by static synchronization methods is the current class itself
  • Deadlock (e.g. two people eat one chopstick, and neither of them gives up one of the chopsticks.

Description:

  1. Different threads occupy the synchronization resources needed by the other party and do not give up. Each thread is waiting for the other party to give up the synchronization resources needed by itself, thus forming a thread deadlock
  2. After a deadlock occurs, there are no exceptions, no hints, but all threads are blocked and cannot continue

Solution:

  1. Special algorithms, principles
  2. Minimize synchronized resource definitions
  3. Try to avoid nested synchronization
  • Mode 3: Lock Lock (new in JDK5.0)

Method: Lock (), unlock()

  • Similarities and differences between synchronized and Lock (use the recommended order Lock -> synchronized code blocks -> synchronized methods)

Same: Both solve thread safety problems different:

  1. The Synchroized mechanism automatically releases the synchronization monitor after the corresponding code logic is executed
  2. Lock Manually starts synchronization and ends synchronization
  • summary
  1. The synchronization method solves the safety problem of the thread
  2. When manipulating synchronized code, only one thread can participate and the other threads wait, which is equivalent to a single-threaded process that is inefficient
  3. It may cause a deadlock

JDK5.0 added thread creation mode

Method 3: Implement the Callable interface

Callable is more powerful than Runnable

  1. In contrast to run(), there can be a return value
  2. Method can throw an exception
  3. Generic return values are supported
  4. You need the FutureTask class, for example, to get the return result

Method 4: Use a thread pool

Note: The creation and destruction of threads will use a large number of resources, such as concurrent threads, which has a significant impact on performance. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

ExecutorService: A true thread pool interface, common subclass ThreadPoolExecutor

  1. void execute(Runnable command): Executes a task/command. It has no return value and is used to execute Runnable
  2. <T> Future<T> submit(Callable<T> task): Performs a task and has a return value. It is usually used to perform Callable
  3. void shutdown(): Disables the connection pool

Executors: Factory classes for tools and thread pools, used to create and return different types of thread pools

  1. Executors. NewCachedThreadPool () : create a according to the need to create a new thread’s thread pool
  2. Executors. NewFixedThreadPool (n) : create a reusable fixed number of threads in the thread pool
  3. Executors. NewSingleThreadExecutos () : only one thread to create a thread pool
  4. Executors. NewScheduledThreadPool (n) : create a thread pool, it can be arranged in a given delay after running commands or on a regular basis