1. Read-write lock ReentrantReadWriteLock
Concepts:
- Read-write locks are designed to solve the problem of multiple threads writing simultaneously and having multiple threads reading at the same time, causing threads to read data before it has been written. A read-write lock is a lock that allows multiple threads to read at the same time, but allows only one thread to write, thereby ensuring data security.
Degradation of read and write locks:
- Why is demotion, because the permissions of write operations are higher than those of read operations, that is, the process from high to low is called demotion. Read and write locks are not allowed to write while reading, but are allowed to read when writing. The process is to acquire a write lock before acquiring a read lock --> release a write lock --> release a read lock.
public class ReentrantReadWriteLockDemo { public static void main(String[] args) { ReentrantReadWriteLock reentrantLock = new ReentrantReadWriteLock(); ReentrantReadWriteLock.WriteLock writeLock = reentrantLock.writeLock(); ReentrantReadWriteLock.ReadLock readLock = reentrantLock.readLock(); //Get Write Lock First writeLock.lock(); System.out.println("Get Write Lock First"); //Get Read Lock Again readLock.lock(); System.out.println("Get Read Lock Again"); //Release Write Lock writeLock.unlock(); //Release Read Lock readLock.unlock(); } }
Can we upgrade the lock?
//Get Read Lock First readLock.lock(); System.out.println("Get Read Lock First"); //Get a write lock again writeLock.lock(); System.out.println("Get a write lock again");
It seems unreasonable that my program has stopped here and I have a new thread writing to it while I am reading. I have read the lock and then I can write.
2. Blocking Queue
Concepts:
- The characteristics of queues: First in, first out, first in, first out of the queue. A blocked queue is one in which a full queue is blocked when a thread puts data from the left to the queue, or when a thread fetches data from the right of the queue, an empty queue is blocked. This is called a blocked queue.
Classification:
Name | brief introduction |
---|---|
ArrayBlockingQueue | Based on Array, Fixed Length, Maximum Length Integer.MAX_VALUE |
LinkedBlockingQueue | Based on chain list, fixed length, maximum length Integer.MAX_VALUE |
DelayQueue | Set a delay time, the delay time can be reached before removal, unbounded blocking queue, producer will not block but consumer will |
PriorityBlockingQueue | Sort using Comparator Comparator, unbounded blocking queue |
SynchronousQueue | Only one element is allowed in the queue, and each insert operation must wait for the deletion of another thread |
LinkedTransferQueue | Unbounded Queue Based on Chain List |
LinkedBlockingDeque | An optional bounded blocking double-ended queue based on the link node. Optional capacity-bound constructor parameters are used as a way to prevent overexpansion. Capacity (if not specified) equals Integer.MAX_VALUE. Link nodes are created dynamically each time they are inserted, unless this causes a double-ended queue to exceed capacity. |
Core approach:
classification | Throw an exception | Boolean and null | block | overtime |
---|---|---|---|---|
Newly added | add(e) | offer(e) | put(e) | offer(e,time,unit) |
delete | remove() | poll(), empty queue returns null | take() | poll(time,unit) |
inspect | element() | peek() |
3. ThreadPool
Concepts:
- The pool used to hold threads, where one thread is used and then put back to the pool to achieve recycling efficiency, but creating too many threads incurs additional overhead and may not improve program efficiency or reduce efficiency.
The Executors Thread Tool class creates a thread pool:
-
newFixedThreadPool creates a specified number of thread pools
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
-
newSingleThreadExecutor creates a single thread pool
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
-
newCachedThreadPool has a flexible thread pool for creating threads, multiple tasks for creating threads, and the number of threads previously set is restored when the task is finished
ExecutorService executorService = Executors.newCachedThreadPool();
Custom thread pool:
-
When creating a thread pool through the Executors tool class, the underlying layer is created through the new ThreadPoolExecutor() object
-
Seven parameters for ThreadPoolExecutor
Parameter Name Interpretation int corePoolSize Number of Core Threads int maximumPoolSize Maximum Threads long keepAliveTime Time to stay alive TimeUnit unit Unit of time BlockingQueue workQueue Blocking Queue ThreadFactory threadFactory Create Thread Factory for Threads RejectedExecutionHandler handler Denial policy with a full queue
Thread pool execution process:
In practice, we don't use the default three ways to create thread pools, because they are all fast enough to cause OOM, more custom thread pools.
4. Fork and Join
Concepts:
- Fork: Split a large task into smaller tasks
- Join: Combine small task results into one result
Use:
Complete the sum of 0-100: requires the difference between two numbers to be less than or equal to 10
First create a task to inherit RecursiveTask
class MyTask extends RecursiveTask<Integer> { private static final Integer NUMBER = 10; private int begin; private int end; private int result; public MyTask(int begin,int end) { this.begin = begin; this.end = end; } @Override protected Integer compute() { if ((end-begin) <= NUMBER){ for (int i = begin; i <= end ; i++) { result += i; } }else { int middle = (begin + end) >> 1; MyTask beginToMiddle = new MyTask(begin, middle); MyTask middleToEnd = new MyTask(middle + 1, end); //Split result beginToMiddle.fork(); middleToEnd.fork(); //Merge results result = beginToMiddle.join() + middleToEnd.join(); } return result; } }
Use forkJoinPool to complete tasks
public class ForkAndJoin { public static void main(String[] args) throws ExecutionException, InterruptedException { ForkJoinPool forkJoinPool = new ForkJoinPool(); MyTask myTask = new MyTask(0,100); ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(myTask); Integer value = forkJoinTask.get(); System.out.println(value); forkJoinPool.shutdown(); } }