Java Basics - Multithreading Stereotypes

1. Implementation of multithreading in Java

1. Implement Runnable

2. Inherit Thread and override the run method.

3. Implement the Callable interface, rewrite the Call method, and use FutureTask to wrap Callable. And passed into the Thread constructor as a task.

4. Thread pool

The difference between the two is that the run method in the Thread class actually calls the run method in the subclass Runnable. If you inherit Thread, you must override the run method.

If a class inherits the Thread class, it is not suitable for multi-thread sharing resources. But the Runnable interface can facilitate resource sharing.

Two, the five states of the thread

Create: new Thread

Ready: The thread queue is queued, waiting for the cpu service.

Run: Get cpu resources. call run method

Blocking: artificial suspension, sleep, wait, suspend, etc., re-enter the ready state after the blocking is cancelled.

Death: The execution of the stop or run method is complete.

At least two threads are started when the java program starts, one is the main method thread and the other is the garbage collection thread

Threads can be forced to run using the join method . Force other methods to enter the ready state during runtime, waiting for the thread to finish executing.

Threads can use the yield method to temporarily yield the operations of one thread to other threads for execution.

Thread priority can use thread.setPriority()

3. Synchronization and deadlock

If a thread is implemented using the Runnable interface, it means that the properties in the class are shared by multiple threads. Then there will be resource synchronization problems. Synchronized code blocks can be used: synchronized{}.

deadlock

Mutual exclusion: Only one thread can use a resource at a time.

Possess and wait: When a thread is waiting for other resources to be allocated, it continues to occupy the allocated resources; or the current thread needs three resources to continue to perform subsequent operations, but one of the resources is being occupied, so the thread Need to continue to wait for resources to be released.

Non-preemption: resources already occupied by threads cannot be forcibly preempted.

Circular waiting: There is a closed process chain, that is, A is waiting for B, and B is waiting for A.

How to prevent deadlock?

1. Add lock order.

2. Locking time limit (the thread requests the added permission, it will give up when it times out, and release the lock it owns at the same time).

3. Deadlock detection.

四、synchronized

Synchronized is a heavyweight lock before jdk1.6, because its implementation directly calls the enter and exit of ObjectMonitor.

But after jdk1.6, the HotSpot team optimized the lock, such as adding adaptive spin, lock elimination, lock coarsening, lightweight lock, and biased lock

When synchronized modifies a code block, the JVM uses two instructions, monitorEnter and monitorExit, to achieve synchronization.

When synchronized modifies the synchronization method, the JVM uses the ACC_SYNCHORNIZED mark to achieve synchronization.

monitorenter, monitorexit, and ACC_SYNCHORNIZED are all implemented based on monitor.

monitor is a synchronization tool, it can also be said to be a synchronization mechanism

5. Lock status

Biased lock: In the case of no competition, the entire synchronization is eliminated, and the CAS operation is not performed

Lightweight locks: When there is no multi-thread competition, compared with heavyweight locks, the performance consumption caused by system mutexes is reduced. If there is lock competition, in addition to the overhead of the mutex itself, there is additional CAS operation overhead.

Spinlock: Reduce unnecessary CPU context switching. When a lightweight lock is upgraded to a heavyweight lock, the spin lock method is used

Lock coarsening: Connect multiple consecutive locking and unlocking operations together and treat them as a collective. Extended into a lock with a larger range.

Lock elimination: When the virtual machine just-in-time compiler is running, it needs to synchronize some codes, but it is detected that there is no lock for shared data competition.

Six, ThreadLocal

Thread local variables, if a ThreadLocal variable is created, each thread accessing this variable will have a local copy of this variable.

When multiple threads operate on this variable, they actually operate on variables in their own local memory. So as to play the role of thread isolation and avoid thread safety problems.

Implementation principle:

Since each thread has its own ThreadLocalMap. It maintains an Entry array, each Entry represents a complete object, the key is the ThreadLocal itself, and the Value is the generic type of ThreadLocal. When each thread sets a value, it will store it in the ThreadLocalMap of the ThreadLocal. The read also uses a ThreadLocal as a reference to find the corresponding key in its own Map, thus realizing thread isolation.

ThreadLocal memory leak

Since the key of ThreadLocalMap is a weak reference of ThreadLocal, if it is GC, but the life cycle of Thread has not ended, the key will disappear, but the value is still there, resulting in a memory leak.

Weak reference: As long as the garbage collection mechanism runs, the memory occupied by the object will be reclaimed regardless of whether the memory space of the JVM is sufficient.

After using ThreadLocal, just call the remove method in time to release the space.

Seven, Synchronized and ReentrantLock

Synchronized is a keyword of the java language, implemented based on the JVM. ReentrantLock is based on JDK's API implementation (usually done through lock and unlock methods)

ReentrantLock adds some functions to synchronized, such as waiting for interruptible, fair lock, selective notification, etc.

Waiting can be interrupted: implement this mechanism through lock.lockInterruptibly()

Synchronized can only be an unfair lock, and ReentrantLock can specify a fair lock or an unfair lock. Fair lock is to wait first to acquire the lock

Synchronized is combined with wait() and notify()/nofityAll() methods to implement the waiting and notification mechanism.

The ReentrantLock class is implemented with the help of the Condition interface and the newCondition() method

ReentrantLock needs to be locked and unlocked through lock and unlock, while synchronized does not need to be released manually.

Eight, Start and Run

When the JVM executes the start method, another thread will be started to execute the Thread's run method. At this time, the effect of multi-threading will be played.

If the run method of Thread is called directly, the method still runs in the main thread and does not have the effect of multi-threading.

Nine, the creation of thread pool

9.1 Two creation methods

Manually create a thread pool through ThreadPoolExecutor

Automatically create thread pools through Executors

9.2 Seven implementation methods

1.Executors.newFixedThreadPool: Create a fixed-size thread pool, which can control the number of concurrent threads, and the excess threads will wait in the queue.

2. Executors.newCachedThreadPool: Create a cacheable thread pool. If the number of threads exceeds the processing requirements, the cache will be recycled after a period of time. If the number of threads is not enough, a new thread will be created.

3.Executors.newSingleThreadExecutor: Create a thread pool with a single number of threads, which can guarantee the execution order of first-in-first-out.

4.Executors.newScheduledThreadPool: Create a thread pool that can execute delayed tasks. 5.Executors.newSingleThreadScheduledExecutor: Create a single-threaded thread pool that can execute delayed tasks.

6. Executors.newWorkStealingPool: Create a thread pool for preemptive execution (task execution order is uncertain) [JDK 1.8 added].

7.ThreadPoolExecutor: The way to manually create a thread pool, it can set up to 7 parameters when it is created.

Guess you like

Origin blog.csdn.net/qq_33351639/article/details/129121493