A deer can follow a sheep when its heart and body follow a sheep when its heart leads
multithreading
- Basic concepts: program, process, thread
- Create and use (two types)
- The life cycle of a thread
- Synchronization of threads (there are three ways to solve thread-safety problems)
- Thread communication
- 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 scheduledvoid setName()
: sets the name of the Thread (Thread has a constructor that can also be named)String getName()
: Returns the name of the threadstatic 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 classesstatic 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 executedstatic 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:
- Processes of the same priority form a first-in, first-out queue (first-come, first-served) and use a time slice policy
- 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
- Create a subclass that extends from Thread
- Override Thread’s run() to write what you want the Thread to do in the run() method
- Create a subclass object of Thread
- Call start() with this object
Method 2: Implement the Runnable interface
- Create a class that implements the Runnable interface
- Implementation classes to implement abstract methods of the Runnable class: run()
- Create an object that implements the class
- Pass this object as an argument to the constructor of The Thread class to create an object of the Thread class
- Call the start() method from the Thread object
Method one, two contrast
The Runnable interface is preferred for development reasons:
- The implementation does not have the limitations of single inheritance of a class
- The implementation is better suited to situations where multiple threads have shared data
Contact:
- The Thread class itself implements the Runnable interface
- 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:
- Daemon threads (e.g. Java gc garbage collection threads)
- 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:
- The Thread class declares sleep() and the Object class declares wait().
- 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
- 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
- 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)
- Shared data: a variable operated by multiple threads, such as ticket in the example
- Synchronization monitor: commonly known as lock (any object of a class can act as a synchronization monitor, i.e. lock)
- Synchronization monitor requirements: Multiple threads must use the same lock together, and the lock must be unique.
- 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
- The synchronization monitor used by non-static synchronization methods is this
- 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:
- 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
- After a deadlock occurs, there are no exceptions, no hints, but all threads are blocked and cannot continue
Solution:
- Special algorithms, principles
- Minimize synchronized resource definitions
- 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:
- The Synchroized mechanism automatically releases the synchronization monitor after the corresponding code logic is executed
- Lock Manually starts synchronization and ends synchronization
- summary
- The synchronization method solves the safety problem of the thread
- 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
- It may cause a deadlock
JDK5.0 added thread creation mode
Method 3: Implement the Callable interface
Callable is more powerful than Runnable
- In contrast to run(), there can be a return value
- Method can throw an exception
- Generic return values are supported
- 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
void execute(Runnable command)
: Executes a task/command. It has no return value and is used to execute Runnable<T> Future<T> submit(Callable<T> task)
: Performs a task and has a return value. It is usually used to perform Callablevoid shutdown()
: Disables the connection pool
Executors: Factory classes for tools and thread pools, used to create and return different types of thread pools
- Executors. NewCachedThreadPool () : create a according to the need to create a new thread’s thread pool
- Executors. NewFixedThreadPool (n) : create a reusable fixed number of threads in the thread pool
- Executors. NewSingleThreadExecutos () : only one thread to create a thread pool
- Executors. NewScheduledThreadPool (n) : create a thread pool, it can be arranged in a given delay after running commands or on a regular basis