JUC High Concurrency Programming Three

Keywords: Java Back-end

7. Callable interface

1. Multiple ways to create threads

Creation MethodRemarks
Integrate Thread ClassNo return value
Implement Runnable InterfaceNo return value
Through the Callable interfaceCan have a return value
Through thread pools

2. Differences between Callable and Runnable interfaces

DifferenceCallableRunnable
Is there a return valueyesno
Whether to throw an exceptionyesno
Method implementations are differentcall methodrun method

Code implementation:

package com.codetip.codejuc.juc.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

// Implement Runnable Interface
class Mythread1 implements Runnable {
    @Override
    public void run() {

    }
}

// Implement Callable Interface
class Mythread2 implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return 200;
    }
}

public class CallOrRunDemo1 {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        // Runnable interface creation thread
        // new Thread(new Mythread1(), "AA").start();

        // Direct use of Callable, error
        // new Thread(new Mythread2(), "AA").start();

        // You can find a class that relates to both Runnable and Callable
        // Runnable interface has implementation class FutrueTask
        // The FctrueTask construct also passes Callable

        // FutureTask
        // FutureTask<Integer> f1 = new FutureTask<>(new Mythread2());
        // new Thread(f1, "AA").start();

        // lambda expression writing
        FutureTask<Integer> f2 = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "  come in Callable");
            return 1024;
        });

        // Create a thread
        new Thread(f2, "jack").start();

        // isDone method can be used to determine if it has been completed
        // while (!f2.isDone()) {
        // System.out.println("Wait...............");
        // }
        // Call the get method of FutureTask
        System.out.println(f2.get());

        // Re-invoke the execution result and return it directly
        System.out.println(f2.get());

        // Main Thread
        System.out.println(Thread.currentThread().getName() + " come Over");


        /**
         * FutureTask principle
         * 1,Do not affect the main thread's tasks, open one thread to execute other threads, do not affect the main thread's tasks
         * For example: 1. Tasks can be summarized uniformly
         *    There are four classmates: 1 Calculation 1+2+32 calculation: 10+11+12.. 503 calculation: 60+614 calculation: 100+200
         *    The second student had a large amount of calculation.
         *    FutureTask Open a separate thread to calculate for 2 classmates, first summarize the 1,3,4 classmates, and finally wait for 2 to complete the calculation, unified summary
         * For example, in the case of an exam, if you make a meeting first, you will not.
         *
         * Summary: only once
         */
    }
}

8. Powerful JUC auxiliary classes

1. CountDownLatch Decrease Count

  • Summary

    • The CountDownLatch class allows you to set a counter, subtract it by 1 using the CountDown method, wait for the counter to be no more than 0 using the await method, and then continue executing the statement following the await method.
    • CountDownLatch has two main methods. When one or more threads call the await method, they block
    • Other threads calling the countDown method subtracts the counter by one (threads calling the countDown method do not block)
    • When the value of the counter changes to 0, the thread blocked by the await method wakes up and continues execution.

Example: The monitor can only lock the door when all six students leave the classroom

// Not with CountDownLatch
package com.codetip.codejuc.juc.callable;

// Demonstrate CountDownLatch
public class CountDownLatchDemo {
    // (CountDownLatch not applicable) The monitor can lock the door only after six students leave the classroom one after another
    public static void main(String[] args) {
        // Six students left the classroom one after another
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "  Classmates leave the classroom");
            }, i + "Classmate").start();
        }
        System.out.println(Thread.currentThread().getName() + "The monitor has begun to lock the door and walk away.");
    }
}

// Use CountDownLatch 
package com.codetip.codejuc.juc.callable;
import java.util.concurrent.CountDownLatch;
// Demonstrate CountDownLatch
public class CountDownLatchDemo {
    // (CountDownLatch not applicable) The monitor can lock the door only after six students leave the classroom one after another
    public static void main(String[] args) throws InterruptedException {
        // Set counter to 6
        CountDownLatch count = new CountDownLatch(6);
        // Six students left the classroom one after another
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "  Classmates leave the classroom");
                // Count minus 1
                count.countDown();
            }, i + "Classmate").start();
        }
        count.await();
        System.out.println(Thread.currentThread().getName() + "The monitor has begun to lock the door and walk away.");
    }
}

2. CyclicBarrier Cyclic Barrier

  • Summary

    • A synchronous auxiliary class that allows a group of threads to wait for each other until a set common barrier is reached, and CyclicBarrier is useful in programs involving a set of fixed-size threads that have to wait for each other from time to time. Because the Barrier can be reused after the waiting thread is released, it is called a circular Barrier.

      Example: Among the seven dragon beads: seven must be assembled to summon the Dragon.

  • Code implementation:

    package com.codetip.codejuc.juc.callable;
    
    import java.util.concurrent.CyclicBarrier;
    
    // Call the Dragon with 7 Dragon Balls
    public class CyclicBarrierDemo {
        // Set Fixed Value
        private static final int num = 7;
    
        public static void main(String[] args) {
            // Create CyclicBarrier
            CyclicBarrier cyclikBarrier = new CyclicBarrier(num, () -> {
                System.out.println("Ha-ha****,Seven dragon beads can summon the Dragon!!!!");
            });
    
            // The process of collecting seven dragon beads
            for (int i = 1; i <= 7; i++) {
                new Thread(() -> {
                    try {
                        System.out.println(Thread.currentThread().getName() + " Star, dragon beads are collected!");
                        wait for
                        cyclikBarrier.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }, String.valueOf(i)).start();
            }
        }
    }
    
    

    Run Screenshot

      

 

3. Semaphore semaphore

  • concept

    • A counted semaphore, conceptually, maintains a license set. If necessary, each acquire() will be blocked before a license is required to be available, and then each release () will add (release) a license. An apricot may release a blocking acquirer, but without using the time of the license object, Semapshore will only count the number of available licenses and Cai Xu will act accordingly.
  • Example: Parking lot. When you get a car, you get a license. The car is full. The parking lot can't enter the car anymore. The others have to wait. When a vehicle leaves and release s a parking space, other vehicles can continue to acquire parking.

Code case:

package com.codetip.codejuc.juc.callable;

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
// 6 cars, 3 parking spaces
public class SemapHore {
    // Define 3 parking spaces
    public static final int semaphoreNum = 3;
    public static void main(String[] args) {
        // Create a semaphore, set the number of licenses
        Semaphore semaphore = new Semaphore(semaphoreNum);
        for (int i = 1; i <= 6; i++) {
            new Thread(() -> {
                try {
                    // Random dwell time
                    int wait = new Random().nextInt(5);
                    // Get a license
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " Car number, got the parking space!!");
                    TimeUnit.SECONDS.sleep(wait);
                    System.out.println(Thread.currentThread().getName() + " -----Car No. 1, out of parking!!,Stopped:" + wait + "second");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // release
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}

Run result:

 

9. ReentrantReadWriteLock Read-Write Lock

1. Pessimistic Lock

  • When you modify data, you assume that others may modify it, so lock it first, and unlock it when the modification is complete.

    • Disadvantages: Concurrency is not supported and efficiency is low

2. Optimistic Lock

  • When you modify data, you think others will not modify it. When you get the data, you will have a version number. When you modify the data, you will change it according to the requirements of this version number. If the version number is inconsistent, others have modified it.

    • Supports concurrency,

3. Read-write lock

  • Read Lock: Shared Lock
  • Write lock: exclusive lock

Both send deadlocks:

Read Lock: There are two read operations, Read 1 and Read 2. Threads can also do other operations while reading. Read 1: Read and write, Read 2: Also reading. Read 1 can't be modified until Read 2 is finished. Read 2 also modifies this, and a deadlock will occur. Read 1 cannot be modified until Read 2 is finished, and Read 2 cannot operate until Read 1 is finished.

Write lock: Thread 1: Write the first record once. Thread 2 performed a write operation on the second record. Thread 1 then modifies the second record. Thread 2 also modifies the first item. A deadlock is sent, and thread 1 and 2 wait for each other to release the lock.

4. Code demonstration:

  1. No read-write lock
package com.codetip.codejuc.juc.readOrWrite;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

// Resource Class
class MyCahe {
    // Create Map Collection
    private volatile Map<String, Object> map = new HashMap<>();

    // Store data
    public void put(String key, Object value) {
        System.out.println(Thread.currentThread().getName() + " Writing+++,Key For:" + key);
        try {
            TimeUnit.MICROSECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // Place data
        map.put(key, value);
        System.out.println(Thread.currentThread().getName() + " write+++Execution complete, Key For:" + key);
    }

    // Read data
    public Object get(String key) {
        Object result = null;
        System.out.println(Thread.currentThread().getName() + " Reading---,Key For:" + key);
        try {
            TimeUnit.MICROSECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // Place data
        result = map.get(key);
        System.out.println(Thread.currentThread().getName() + " read---Finish execution, Key For:" + key);
        return result;
    }
}

public class ReadWriteLockDemo1 {
    public static void main(String[] args) {
        MyCahe myCahe = new MyCahe();
        // Create Threads to Put Data
        for (int i = 1; i <= 3; i++) {
            final int num = i;
            new Thread(() -> {
                myCahe.put(num + "", num + "");
            }, String.valueOf(i)).start();
        }
        // Create thread to fetch data
        for (int i = 1; i <= 3; i++) {
            final int num = i;
            new Thread(() -> {
                myCahe.get(num + "");
            }, String.valueOf(i)).start();
        }
    }
}

Run result:

 

2. Add Read-Write Lock

package com.codetip.codejuc.juc.readOrWrite;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

// Resource Class
class MyCahe {
    // Create Map Collection
    private volatile Map<String, Object> map = new HashMap<>();

    //Object to create read-write locks
    ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    // Store data
    public void put(String key, Object value) {
        // Add Write Lock
        readWriteLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " Writing+++,Key For:" + key);
            TimeUnit.MICROSECONDS.sleep(300);
            // Place data
            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + " write+++Execution complete, Key For:" + key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // Release Write Lock
            readWriteLock.writeLock().unlock();
        }
    }

    // Read data
    public Object get(String key) {
        Object result = null;
        // Add Read Lock
        readWriteLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " Reading---,Key For:" + key);
            TimeUnit.MICROSECONDS.sleep(300);
            // Place data
            result = map.get(key);
            System.out.println(Thread.currentThread().getName() + " read---Finish execution, Key For:" + key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // Release Read Lock
            readWriteLock.readLock().unlock();
        }
        return result;

    }
}

public class ReadWriteLockDemo1 {
    public static void main(String[] args) {
        MyCahe myCahe = new MyCahe();
        // Create Threads to Put Data
        for (int i = 1; i <= 3; i++) {
            final int num = i;
            new Thread(() -> {
                myCahe.put(num + "", num + "");
            }, String.valueOf(i)).start();
        }
        // Create thread to fetch data
        for (int i = 1; i <= 3; i++) {
            final int num = i;
            new Thread(() -> {
                myCahe.get(num + "");
            }, String.valueOf(i)).start();
        }
    }
}


Execution effect:

 

5. Deep Read-Write Lock

  • Read-write lock: A resource can be accessed by multiple read threads at the same time or by a write thread, but there are different read-write threads at the same time. Read-write is mutually exclusive and read-read is shared

The evolution of read-write locks:

First unlockSecond: Add a lockThird: Read-write lock ReentrantReadWriteLock
Multi-threaded grab resources (chaotic)Using synchronized and ReentrantLockRead and read can be shared to improve performance, while multiple people can read and operate
Is exclusive, can only operate one at a timeWrite or One
Disadvantages: Read oneDisadvantages: 1: Lock hunger (read all the time, no write)
Write one2: When you read, you cannot write. You can only write when you have finished reading.

6. Lock Degradation

  • Demotes a write lock to a read lock, with write permissions greater than read permissions.

    • You can only downgrade from a write lock to a read lock. Cannot upgrade from a read lock to a read lock
  • Demotion process:

  Note: This is the mermaid syntax in MarkDown and the result is the image above

flowchart LR
    id1[Get Write Lock]-->id2[Acquire Read Lock]-->
    id3[Release Write Lock]-->id4[Release Read Lock]
package com.codetip.codejuc.juc.readOrWrite;
import java.util.concurrent.locks.ReentrantReadWriteLock;
// Lock Demotion Demo
public class LockDemotion {
    public static void main(String[] args) {
        // Create a reentrant lock
        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        // Write lock
        ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
        // Read Lock
        ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
        try {
            // Get Write Lock
            writeLock.lock();
            System.out.println("+++++Writing!!!");
            // Acquire Read Lock
            readLock.lock();
            System.out.println("-----Reading operation!!!!");
        } finally {
            // Release Write Lock
            writeLock.unlock();
            // Release Read Lock
            readLock.unlock();
        }
    }
}

10. BlockingQueue Blocking Queue

1. Review the data structure first

queueStack
FIFOFIFO

2. Blocking queue:

  1. As the name implies, first it is a queue, through which data can be input from one end of the queue and output from the other end.
  • When the queue is empty, getting elements from the queue will be blocked until other threads insert new elements into the empty queue
  • When the queue is full, adding elements to the queue will be blocked until another thread removes one or more elements from the queue or empties them altogether, leaving the queue idle and adding them later.

In multithreaded environments, so-called blocking suspends the thread (i.e., blocking) in some cases, and once the condition is met, the suspended thread is automatically awakened for execution

 

  Note: This is the mermaid syntax in MarkDown and the result is the image above

flowchart LR
Thread1-->|Put|BlockingQueue-->|Take|Thread2

3. Code architecture for blocking queues

java.util.concurrent interface BlockingQueue

  • Type parameters:

    E - Element types maintained in this collection

  • All Super Interfaces:

    Collection, Iterable, Queue

  • All known subinterfaces:

    BlockingDeque

  • All known implementation classes:

    ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue

4. Classification of blocking queues

Queue Class Nameexplain
ArrayBlockingQueue (commonly used)Bounded blocking queue composed of array structure
LinkedBlockingQueue (Common)Bounded blocking queue composed of a chain table structure (default size: Integer. MAX_VALUE)
DelayQueueDelayed unbounded blocking queue using priority queue
PriorityBlockingQueueUnbounded blocking queue supporting priority ordering
SynchronizedQueueA blocking queue that does not store elements, that is, a queue of individual elements
LinkedTransferQueueAn unbounded blocking queue consisting of a list of chains
LinkedBlockingDequeA two-way blocking queue consisting of a list of chains

  • Core methods of queues
Method TypethrowSpecial Valuesblockovertime
insertadd(e)offer(e)put(e)offer(time,unit)
removeremove(e)poll()take()poll(time,unit)
inspectelement(e)peek()Not availableNot available

Namedescribe
throwWhen the queue is full: add element to the queue, throw: java.lang.IllegalStateException: Queue full exception
When the queue is empty: remove element from the queue, throw: main "java.util.NoSuchElementException exception"
Special ValuesInsert method: Return true successfully, Fail false, Remove method: Return elements in queue successfully, Return nul inside
blockWhen the blocking queue is full, the producer thread continues to put elements into the queue, and the queue will block the producer thread until the putdataor interrupts and exits accordingly
When the blocking queue is empty, the consumer thread attempts to take elements from the queue, and the queue blocks the consumer thread until the queue is available
overtimeWhen the blocking queue is full, the queue blocks the producer thread for a certain period of time, after which the producer thread exits

5. Starter Cases

package com.codetip.codejuc.juc.BlockingQueue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class BlockingQueueDemo01 {
    public static void main(String[] args) throws InterruptedException {
        // Create a fixed-length rental queue
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
        // Group 1 Cases
//        System.out.println(blockingQueue.add("a"));
//        System.out.println(blockingQueue.add("b"));
//        System.out.println(blockingQueue.add("c"));
//        System.out.println(blockingQueue.add("d"));
//        System.out.println(blockingQueue.element());
//        System.out.println(blockingQueue.remove());

        // Group 2
//        System.out.println(blockingQueue.offer("a"));
//        System.out.println(blockingQueue.offer("b"));
//        System.out.println(blockingQueue.offer("c"));
//        System.out.println(blockingQueue.offer("d"));
//
//        System.out.println(blockingQueue.poll());
//        System.out.println(blockingQueue.poll());
//        System.out.println(blockingQueue.poll());
//        System.out.println(blockingQueue.poll());

        // Group 3
//        blockingQueue.put("a");
//        blockingQueue.put("b");
//        blockingQueue.put("c");
//        blockingQueue.put("d");
//        blockingQueue.take();
//        blockingQueue.take();
//        blockingQueue.take();
//        blockingQueue.take();

        // Group 4
        System.out.println(blockingQueue.offer("a", 2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("b", 2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("c", 2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.offer("d", 2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));
        System.out.println(blockingQueue.poll(2L, TimeUnit.SECONDS));


    }
}

11. ThreadPool Thread Pool

1. Overview of thread pools

  • Concepts:

    • A thread usage pattern. Too many threads incur overhead that can impact cache locality and overall performance. Thread pools maintain multiple threads and wait for supervisors to assign executable tasks, which avoids the cost of creating and destroying threads when dealing with short tasks. Thread pools not only ensure full utilization of the kernel, but also prevent overscheduling. .

2. Thread pool architecture

 

 

  Note: This is the mermaid syntax in MarkDown and the result is the image above

 classDiagram
 	class Tool class Executors{
	}
  Interface Execure <|-- Interface ExecutorService : inherit
  Interface ExecutorService <|.. Free Class AbstractExecutoService : Realization
  Free Class AbstractExecutoService <|-- Implementation Class ThreadPoolExecutor : inherit
  Implementation Class ThreadPoolExecutor <|.. Implementation Class ThreadPoolExecutor
  Implementation Class ThreadPoolExecutor <|-- Implementation Class ScheduleThreadPoolExecutor  : inherit
  
  Interface ExecutorService <|-- Interface ScheduleExecutoService : inherit
  Interface ScheduleExecutoService <|.. Implementation Class ScheduleThreadPoolExecutor: Realization

3. How thread pools are used

Create a thread pool using the Executors tool class

Methoddescribe
Executors.newFixedThreadPoolA fixed-size thread pool
Executors.newSingleThreadExecutorOne task, one task execution, one thread pool, one task.
Executors.newCachedThreadPoolThread pools create threads on demand, scalable, strong

Code demonstration

package com.codetip.codejuc.juc;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolDemo001 {
    public static void main(String[] args) {
        // One pool with five threads
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        try {
            for (int i = 1; i <= 10; i++) {
                threadPool.execute(() -> System.out.println(Thread.currentThread().getName() + "  Business in progress!!!"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }
        System.out.println("-------------------------Split Line-----------------------");
        // One pool, one route
        ExecutorService threadSingle = Executors.newSingleThreadExecutor();
        try {
            for (int i = 1; i <= 10; i++) {
                threadSingle.execute(() -> System.out.println(Thread.currentThread().getName() + "  Business in progress!!!"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadSingle.shutdown();
        }
        System.out.println("-------------------------Split Line-----------------------");
        // Bufferable threads
        ExecutorService executorService = Executors.newCachedThreadPool();
        try {
            for (int i = 1; i <= 10; i++) {
                executorService.execute(() -> System.out.println(Thread.currentThread().getName() + "  Business in progress!!!"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown();
        }
    }
}

Thread Pool Bottom Principle

The above method for viewing source discovery using thread pools created by Executors is: ThreadPoolExecutor

4. Seven parameters of thread pool

  • ThreadPoolExecutor parameter description

    Class name: ThreadPoolExecutorExplain
    int corePoolSizeNumber of resident (core) threads
    int maximumPoolSizeMaximum Threads
    Long keepAliveTimeThe thread's lifetime (how long does it take to destroy without using it, keeping the number of core threads)
    TimeUnit unitUnits of survival time
    BlockingQueue workQueueBlocking Queue
    ThreadFactory threadFactoryThread Engineering
    RejectedExecutionHandler handlerRejection Policy

5. Thread pool underlying workflow

 

  • Execute process

    • First, submit the task to invoke execute, second, the core thread will execute the task; Third, there are so many tasks that the core thread cannot execute at the same time and it will be put in the blocking queue

    • Step 4: If the blocked queue is full, a new thread will be created to perform the task, and the total number of threads will not be greater than the total number of threads set.

    • Step 5: Continue with new tasks and no new threads to create. Rejection policy will be executed.

      • Built-in Resolution Policy

        Decisive strategydescribe
        AbortPolicyBy default, RejectedExecutionHandler exceptions are thrown directly, organizing the system to function properly
        CallerRunsPolicyThe caller runs "Run a tuning mechanism that does not discard tasks or throw exceptions. Instead, it returns a learning task to the caller, which reduces the flow of new tasks
        DiscardOldestPolicyDiscard the task that has been waiting the longest in the queue, then add the current task to the queue and try to submit the task again
        DiscardPolicyThis policy directly discards tasks that cannot be handled, does not handle them, and does not throw any exceptions. This is the best policy if loss is allowed.

      Importantly, creating a thread pool in a project by using ThreadPoolExecutor is not recommended, as is the common Executors tool class. This allows students writing to understand the rules of the thread pool and avoid the risk of resource exhaustion by creating their own thread pool by using ThreadPoolExecutor.

      The risks and disadvantages of objects that Executors creates thread pools are as follows

      MethodExplain
      FixedThreadPool and SingleThreadExecutorAllowed request queue length is Integer.MAX_VALUE, which can cause a lot of requests to accumulate, resulting in OOM
      CachedThreadPool and SchduledThreadPoolThe number of threads allowed to be created is Integer.MAX_VALUE, which may create a large number of threads, resulting in OOM

6. Custom Thread Pool

The code is as follows:

package com.codetip.codejuc.juc.ThreadPool;

import java.util.concurrent.*;

// Create a custom thread pool
public class ThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = new ThreadPoolExecutor(
                5,// Core Thread Size
                7, // Maximum Threads
                2L, // The thread's lifetime (how long does it take to destroy without using it, keeping the number of core threads)
                TimeUnit.SECONDS,// Survival time unit
                new ArrayBlockingQueue<>(3),// Blocking Queue
                Executors.defaultThreadFactory(), // Thread Engineering
                 new ThreadPoolExecutor.AbortPolicy() // Rejection Policy
        );

        try {
            for (int i = 1; i <= 10; i++) {
                service.execute(() -> System.out.println(Thread.currentThread().getName() + "  Business in progress!!!"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            service.shutdown();
        }





    }
}

Posted by Vijay.Bansode on Sat, 04 Dec 2021 09:12:03 -0800