Summary of JUC multithreaded programming

Keywords: Java Back-end

Summary of JUC multithreaded programming

JUC: use of java.util.concurrent multithreading Toolkit

Test demo:https://gitee.com/aqq/mytest.git

1. Daemon thread

There are two kinds of threads in java: user thread and daemon thread

Only if the user thread in the current JVM does not end, the daemon thread will work. Only when the last user thread ends, the daemon thread will work with the JVM. For example, garbage collection (GC) in the JVM is the daemon thread.

Thread thread = new Thread();
// Set thread as a daemon thread, default false (non daemon thread)
thread.setDaemon(true)
  
//isDaemon is used to determine whether a thread is a daemon thread
thread.isDaemon();
 

be careful:

1. thread.setDaemon(true) must be before thread.start(), otherwise an IllegalThreadStateException will be thrown, and the running thread cannot be set as a daemon thread

2. The new thread generated in the Daemon thread is also a Daemon thread

3. No task. All threads can be assigned to Daemon to perform services, such as read-write operations or computational logic

2. Use of Synchronized

Simulate the scene of three conductors selling 30 tickets

/**
 * Simulate the scenario of three conductors selling 30 tickets
 * 1,First, define resources and resource attributes
 *
 */
public class SaleTickets {

    public static void main(String[] args) {
        Tickets tickets = new Tickets();

        Thread thread1 = new Thread(new SaleThread(tickets), "AA");
        Thread thread2 = new Thread(new SaleThread(tickets), "BB");
        Thread thread3 = new Thread(new SaleThread(tickets), "CC");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}
class SaleThread implements Runnable{

    private Tickets tickets;

    public SaleThread(Tickets tickets) {
        this.tickets = tickets;
    }
    @Override
    public void run() {
        for(int i = 0;i<120;i++){
            tickets.sail();
        }
    }
}
class Tickets{

    private int numbers = 100;

    public synchronized void sail(){

        if(numbers>0){

            System.out.println(Thread.currentThread().getName() + "Sold: 1 piece, remaining:" + (numbers--) + "Zhang");
        }
    }
}

3. Use of Lock

Use of reentrant lock: it also simulates the scenario of three conductors selling 30 tickets

When calling the lock.lock() method, there must be a call to release the lock (lock.unlock()), which is best written in finally

public class LSaleTickets {

    public static void main(String[] args) {

        Tickets tickets = new Tickets();

        Thread thread1 = new Thread(new SaleThread(tickets), "AA");
        Thread thread2 = new Thread(new SaleThread(tickets), "BB");
        Thread thread3 = new Thread(new SaleThread(tickets), "CC");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

/**
 * Create resource object
 **/
class Tickets{

    //Number of tickets
    private int numbers = 30;

    //Create a reentrant lock
    private final ReentrantLock lock = new ReentrantLock();

    //Buy a ticket
    public void sale(){
        lock.lock();

        try{
            //Judge whether there are tickets
            if (numbers > 0) {
                System.out.println(Thread.currentThread().getName() + "Sold: 1 piece, remaining:" + (numbers--) + "Zhang");
            }
        }finally {
            lock.unlock();
        }
    }
}
//Define the thread for selling tickets
class SaleThread implements Runnable{

    private Tickets tickets;

    public SaleThread(Tickets tickets) {
        this.tickets = tickets;
    }

    @Override
    public void run() {
        for(int i = 0;i<40;i++){
            tickets.sale();
        }
    }
}
4. Inter thread communication, false wake-up

Inter thread communication mainly uses wait() and notifyAll() methods, or await() and signalAll() of Condition class to control the waiting and waking of threads, so as to realize inter thread communication

Case 1: implement a + 1 and a - 1 operation through the synchronized keyword and the wait and notify methods

package com.vike.juctest.sync;
/**
 * Simulate inter thread communication
 * if(num!=0){
 *     this.wait();//Wake up wherever you sleep
 * }
 * If you use if, there will be a false wake-up problem, because the if condition is judged only once and should be while
 * while(num!=0){
 *     this.wait();
 * }
 */
public class ThreadTransf {

    public static void main(String[] args) {
        Share share = new Share();
        new Thread(()->{
            for (int i =0;i<10;i++){
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"AA").start();

        new Thread(()->{
            for (int i=0;i<10;i++){
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"BB").start();

        new Thread(()->{
            for (int i =0;i<10;i++){
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"CC").start();

        new Thread(()->{
            for (int i=0;i<10;i++){
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"DD").start();
    }
}
/**
 * Create resource class
 */
class Share{
    private int number = 0;

    /**
     * +1 method
     */
    public synchronized void incr() throws InterruptedException {
        while (number != 0) {
            this.wait();
        }
        number++;
        System.out.println(Thread.currentThread().getName()+"::data+1 after::"+number);
        this.notifyAll();
    }

    /**
     * -1 method
     */
    public synchronized void decr() throws InterruptedException {
        while (number != 1) {
            this.wait();
        }
        number--;
        System.out.println(Thread.currentThread().getName()+"::data-1 after::"+number);
        this.notifyAll();
    }
}


Case 2: it is implemented through Lock. The await() and signalAll() methods of Condition class are required to wait and wake up

package com.vike.juctest.lock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Inter thread communication 2 takes the form of lock
 */
public class ThreadTransf2 {

    public static void main(String[] args) {
        Share share = new Share();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                share.incy();
            }
        }, "AA").start();

        new Thread(()->{
            for (int i=0;i<10;i++){
                share.decy();
            }
        },"BB").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                share.incy();
            }
        }, "CC").start();

        new Thread(()->{
            for (int i=0;i<10;i++){
                share.decy();
            }
        },"DD").start();
    }
}

/**
 * Define resources
 */
class Share{

    private int number = 0;

    final ReentrantLock lock = new ReentrantLock();
    final Condition condition = lock.newCondition();

    /**
     * Define the method of adding 1
     */
    public void incy(){
        lock.lock();

        try {
            while (number!=0){
                //Current thread waiting
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"::data+1 after::"+number);
            //Wake up other threads
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    /**
     * Define the method of subtracting 1
     */
    public void decy(){
        //Lock
        lock.lock();
        try {
            while (number != 1) {
                //Thread waiting
                condition.await();
            }
            number--;
            //Wake up other threads
            condition.signalAll();
            System.out.println(Thread.currentThread().getName()+"::data-1 after::"+number);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //Unlock
            lock.unlock();
        }
    }
}

Case 3: customized communication between threads

  • Customized communication between threads

  • AA, BB and CC threads are executed in sequence

  • The status is 1, AA executes 5 times, the status is changed to 2, and BB is notified to execute,

  • The status is 2, BB executes 10 times, the status is changed to 3, and CC is notified to execute

  • The status is 3, CC executes 15 times, the status is changed to 1, and AA is notified to execute

    public class ThreadTransf3 {
        public static void main(String[] args) {
    
            ShareResource shareResource = new ShareResource();
    
            new Thread(()->{
                for (int i =1;i<3;i++){
                    try {
                        shareResource.printAA(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"AA").start();
    
            new Thread(()->{
                for (int i =0;i<2;i++){
                    try {
                        shareResource.printBB(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"BB").start();
    
            new Thread(()->{
                for (int i =0;i<2;i++){
                    try {
                        shareResource.printCC(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"CC").start();
        }
    }
    
    /**
     * Define resource classes
     */
    class ShareResource{
        //Define thread status 1:AA thread execution 2: BB thread execution 3: CC thread execution
        private int flag = 1;
        final ReentrantLock lock = new ReentrantLock();
        final Condition conditionA = lock.newCondition();
        final Condition conditionB = lock.newCondition();
        final Condition conditionC = lock.newCondition();
    
        public void printAA(int loop) throws InterruptedException {
            lock.lock();
            try {
                //Judgment conditions
                while (flag != 1) {
                    conditionA.await();
                }
                //work
                for (int i=1;i<6;i++){
                    System.out.println(Thread.currentThread().getName() + "::Number of rounds" + loop + ",Print:" + i);
                }
                flag=2;
                //Notify other threads
                conditionB.signal();
            }finally {
                lock.unlock();
            }
        }
    
        public void printBB(int loop) throws InterruptedException {
            lock.lock();
            try {
                //Judgment conditions
                while (flag != 2) {
                    conditionB.await();
                }
                //work
                for (int i=1;i<11;i++){
                    System.out.println(Thread.currentThread().getName() + "::Number of rounds" + loop + ",Print:" + i);
                }
                flag=3;
                //Notify other threads
                conditionC.signal();
            }finally {
                lock.unlock();
            }
        }
    
        public void printCC(int loop) throws InterruptedException {
            lock.lock();
            try {
                //Judgment conditions
                while (flag != 3) {
                    conditionC.await();
                }
                //work
                for (int i=1;i<16;i++){
                    System.out.println(Thread.currentThread().getName() + "::Number of rounds" + loop + ",Print:" + i);
                }
                flag=1;
                //Notify other threads
                conditionA.signal();
            }finally {
                lock.unlock();
            }
        }
    }
    
5. Collective security
List:

ArrayList thread is unsafe. There are three alternatives

1)Vector vector = new Vector();
2) Collections tool class: List = collections.synchronizedlist (New ArrayList < > ());

3)CopyOnWriteArrayList: List list = new CopyOnWriteArrayList();

Set:

HashSet thread is unsafe. The alternative is CopyOnWriteSet

Map:

HashMap thread is unsafe. The alternative is: ConcurrentHashMap

package com.vike.juctest.collection;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Thread safety issues for collections
 *
 */
public class ThreadCollertion {

    public static void main(String[] args) {

        ThreadCollertion threadCollertion = new ThreadCollertion();
//        threadCollertion.mainList();
//        threadCollertion.mainSet();
        threadCollertion.mainmap();
    }

    public void mainList(){

//        List list = new ArrayList();

//        List list = new Vector();

//        List list = Collections.synchronizedList(new ArrayList<>());

        List list = new CopyOnWriteArrayList();

        for (int i = 0; i < 30; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }

    public void mainSet(){
//        Set<String> set = new HashSet<>();
        Set<String> set = new CopyOnWriteArraySet<>();
        for (int i = 0; i < 30; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0, 8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }


    public void mainmap(){
//        Map<String, String> map = new HashMap<>();

        Map<String, String> map = new ConcurrentHashMap<>();
        for (int i = 0; i < 30;i++) {
            String key = String.valueOf(i);
            new Thread(() -> {
                map.put(key, UUID.randomUUID().toString().substring(0, 8));
                System.out.println(map);
            }, String.valueOf(i)).start();
        }
    }
}

6. Multithreaded lock

Fair lock and unfair lock, cases: ticket buying cases, thread AA may sell all the tickets, while BB and CC do not sell the tickets,

Fair lock: it is inefficient and needs to be judged whether it is fair or not

Unfair lock: high efficiency, thread starvation

private final ReentrantLock lock = new ReentrantLock(false);// Unfair lock

private final ReentrantLock lock = new ReentrantLock(true);// Fair lock

Deadlock: when two or more processes are executing, they wait for each other because they compete for resources. If there is no external interference, they can no longer execute

Deadlock: you can view the java thread id through jps -l, and then view the thread deadlock through jstack thread id

public class DeadLock {

    public static void main(String[] args) {
        Object a = new Object();
        Object b = new Object();

        new Thread(()->{
            synchronized (a){
                System.out.println(Thread.currentThread().getName()+": Hold lock a,Attempt to acquire lock b");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (b){
                    System.out.println(Thread.currentThread().getName()+":Acquire lock b");
                }
        }
        },"a").start();


        new Thread(()->{
            synchronized (b){
                System.out.println(Thread.currentThread().getName()+": Hold lock b,Attempt to acquire lock a");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a){
                    System.out.println(Thread.currentThread().getName()+":Acquire lock a");
                }
            }
        },"b").start();
    }
}
7. Implementation of multithreading

Four ways to implement multithreading

Comparison between Runnable and Callable methods

1) Whether there are return parameters: Callable has return parameters

2) Whether to return an exception externally: Callable calls the call method to return an exception

3) The implementation methods are different. One is the run method and the other is the call method

######1) Integrated Thread class

class MyThread extends Thread{

    @Override
    public void run() {
        System.out.println("Thread execution");
    }
}

######2) Implement Runnable interface

class TheradRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " run Method execution");
    }
}

######3) Implement Callable interface

class ThreadCallable implements Callable<Integer>{

    @Override
    public Integer call() throws Exception {
        System.out.println(Thread.currentThread().getName() + " call Method execution");
        return 200;
    }
}

######4) Thread pool mode

Detailed description below

8. Use of auxiliary classes (counter, cycle fence, signal lamp)
1) Countdownlatch (counter)

Simulation scenario: there are 6 students on the scene. After the last student leaves, the monitor locks the door

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatchDemo demo = new CountDownLatchDemo();
//        demo.test1();
        demo.test2();
    }
    /**
     * When CountDownLatch is not used
     */
    public void test1(){

        for (int i = 1; i < 7; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "Classmate No. 1 left the classroom");
            }, String.valueOf(i)).start();
        }
        System.out.println("The monitor locked the door");
    }

    /**
     * When countdown latch is not adopted, the monitor is not the last to lock the door
     * When using CountDownLatch
     */
    public void test2() throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 1; i < 7; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "Classmate No. 1 left the classroom");
                countDownLatch.countDown();
                System.out.println("Number of remaining students:"+countDownLatch.getCount());
            }, String.valueOf(i)).start();
        }

        System.out.println("The monitor waited for the last student to leave");
        countDownLatch.await();
        System.out.println("The monitor locked the door");

    }
}
2) Cyclicbarrier
/**
 * Cyclic barrier
 * CyclicBarrier Looking at the English words, we can roughly see that it means circular blocking. In use, the first parameter of the construction method of CyclicBarrier is the number of target obstacles. If the blocking reaches the target
 * The statement after cyclicBarrier.await() will be executed only after the number of obstacles. CyclicBarrier can be understood as plus 1 operation
 *
 * Simulation scenario: collect 7 dragon balls to summon the dragon
 */
public class CyclicBarrierDemo {

    private static final Integer NUMBER = 7;
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER,()->{
            System.out.println("Collect 7 dragon balls and you can summon the dragon");
        });

        for (int i = 1; i < 8; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "The star beads have been collected");
                    cyclicBarrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }
    }
}
3) Semaphore (signal light)
/**
 * Semaphore Signal lamp
 * A counting semaphore. Conceptually, semaphores maintain a permission set. If necessary, an acquire() will be blocked before the permission is available, and then the permission will be obtained
 * Each release() adds a license, which may release a blocked acquisition. However, without using the actual license object, Semaphore only counts the available license numbers,
 * And take corresponding actions
 *
 * Example: six cars grab three parking spaces
 *
 */
public class SemaphoreDemo {

    public static void main(String[] args) {

        //Create Semaphore and set the number of licenses
        Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < 6; i++) {
            new Thread(() -> {

                try {
                    //Preemptive license
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " Grabbed the parking space");

                    int timeForTC = new Random().nextInt(5);
                    System.out.println(Thread.currentThread().getName() + "parking" + timeForTC + "second");
                    //Randomly set parking time
                    TimeUnit.SECONDS.sleep(timeForTC);

                    System.out.println(Thread.currentThread().getName()+" -----------Left the parking space");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    semaphore.release();
                }
            }, String.valueOf(i + 1)).start();
        }
    }
}
9. Read write lock

1. Read locks are shared locks and write locks are exclusive locks

2. Read and write are mutually exclusive and shared

/**
 * Read write lock
 * Read locks are shared locks that can be shared by multiple threads
 * When writing a lock, the lock is exclusive and can only be occupied by a single thread
 * Reading and writing are mutually exclusive
 * Reading is shared
 * synchronized And ReentrantLock are exclusive locks
 */
public class ReadWriteLockDemo {

    public static void main(String[] args) {

        MyCache cache = new MyCache();

        //Create deposit thread
        for (int i = 0; i < 3; i++) {
            final int num =i;
            new Thread(() -> {
                cache.put(String.valueOf(num), String.valueOf(num));
            }, String.valueOf(i)).start();
        }

        //Create read thread
        for (int i = 0; i < 3; i++) {
            final int num =i;
            new Thread(() -> {
                Object o = cache.get(String.valueOf(num));
            }, String.valueOf(i)).start();
        }

    }
}

/**
 * Define resource classes
 */
class MyCache {

    private volatile Map<String, Object> map = new HashMap<>();

    ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();

    /**
     * map Intermediate amplification value
     */
    public void put(String key,Object value){

        ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
        try {
            writeLock.lock();
            System.out.println(Thread.currentThread().getName() + "Writing" + key);
            TimeUnit.MICROSECONDS.sleep(300);

            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "Finished" + key);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
    }

    /**
     * map Medium value
     */
    public Object get(String key){
        Object result = null;
        ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
        try {
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + "Reading operation" + key);
            TimeUnit.MICROSECONDS.sleep(300);

            result = map.get(key);
            System.out.println(Thread.currentThread().getName() + "Finished reading" + key + ",Value is" + result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            readLock.unlock();
        }
        return result;
    }
}
10. Blocking queue

Blocking queue

When the elements in the queue are full, putting values in the queue will block

When the element in the queue is empty, the re value will be blocked

Queue: FIFO stack: LIFO

The API s in the queue are divided into four groups

  • Throw exception: add(e),remove(),element()

  • Return special values: offer(e),poll(),peek()

  • Blocking: put(e),take()

  • Timeout exit: offer(e,time,unit),poll(time,unit)

    public class BlockingQueueDemo {
    
        public static void main(String[] args) throws InterruptedException {
            ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
    
            /**
             * Group 1: add(): value setting. Exceptions will be thrown when the queue is full
             * remove():Value. When the queue is empty, an exception will be thrown
             * elemeng():Determine whether the queue has a value
             */
    
    
    //        System.out.println(queue.add("a"));
    //        System.out.println(queue.add("b"));
    //        System.out.println(queue.add("c"));
    
    //        System.out.println(queue.add("w"));
    //        System.out.println(queue.remove());
    //        System.out.println(queue.remove());
    //        System.out.println(queue.remove());
    //        System.out.println(queue.remove());
    //        System.out.println(queue.add("a"));
    //        System.out.println(queue.element());
    //        System.out.println(queue.element());
            /**
             * Group 2:
             * offer():If the value is not full, return true; otherwise, return false
             * poll():Value. If it is empty, it returns null; otherwise, it returns true
             * peek():Judge whether there is a value. If there is a value, return true; otherwise, return null
             */
    //        System.out.println(queue.offer("a"));
    //        System.out.println(queue.offer("b"));
    //        System.out.println(queue.offer("c"));
    //        System.out.println(queue.offer("w"));
    //        System.out.println(queue.poll());
    //        System.out.println(queue.poll());
    //        System.out.println(queue.offer("a"));
    //        System.out.println(queue.peek());
    
            /**
             * Group 3
             * put(e): Value setting
             * take(): Value
             */
            queue.put("a");
            queue.put("a");
            queue.put("a");
    //        queue.put("a");
    
            /**
             * Group 4:
             * offer(e,time,unit): If the blocking time exceeds unit, it will not wait
             * poll(time,unit): Value. If the blocking time exceeds unit, it will not wait
             */
            queue.offer("a", 1l, TimeUnit.SECONDS);
            queue.offer("a", 1l, TimeUnit.SECONDS);
            queue.offer("a", 1l, TimeUnit.SECONDS);
            queue.offer("a", 1l, TimeUnit.SECONDS);
    
        }
    }
    
11. Thread pool
  • advantage:

  • 1. Reduce resource consumption by reusing created threads to reduce the consumption caused by thread creation and destruction

  • 2. Improve the response speed. When the task reaches, the task can be executed immediately without waiting for the thread to be created

  • 3. Improve the manageability of threads. Threads are scarce resources. If they are created without restrictions, they will not only consume system resources, but also reduce the stability of the system

    To create a thread pool, use the toolbar executors. Thread pool classification:

    • 1) Newfixedthreadpool (common): create a reusable thread pool with a fixed number of threads, run these threads in the way of sharing an unbounded queue, and all threads in the thread pool are running

    • When an additional thread is added again, the thread waits in the queue until there are available threads

    • Features: 1. The number of threads in the thread pool is fixed, which can well control the concurrency of threads. 2

    • 2. Threads can be reused and exist until they are explicitly closed

    • 3. When more than a certain number of threads are submitted, they need to wait in the queue

    • 2) newSingleThreadExecutor(), thread pool of single thread
      *

      1. newCachedThreadPool(), thread pool with variable number of threads

      The construction methods of the three thread pools are implemented through the ThreadPoolExecutor class

      Detailed explanation of construction method parameters of ThreadPoolExecutor class

      • int corePoolSize: number of core threads, number of resident threads

      • int maximumPoolSize: the maximum number of threads in the thread pool

      • long keepAliveTime: the thread lifetime. When the number of threads exceeds the number of core threads and is inactive, it will be recycled after exceeding keepAliveTime

      • Timeunit: thread lifetime unit

      • BlockingQueue workQueue: blocking queue

      • ThreadFactory threadFactory: thread factory, used to create threads

      • Rejectedexecutionhandler: rejection policy, which refers to the rejection policy when the maximum number of threads is reached

      • Core threads > blocking queue > maximum threads > reject policy

      • 1. When there is a thread request, it runs through the core thread first

      • 2. When the core thread reaches the maximum, a new thread is added to the blocking queue

      • 3. When the blocking queue reaches the maximum and the thread pool does not reach the maximum number of threads, a new thread will be created and the new thread will be executed first

      • 4. When the thread pool reaches the maximum number of threads and a new thread arrives, the reject strategy is adopted

       ```java
       public class Demo1 {
      
           public static void main(String[] args) {
               //Reusable fixed capacity thread pool
               ExecutorService executorService = Executors.newFixedThreadPool(5);
      
               //Single threaded thread pool
       //        ExecutorService executorService = Executors.newSingleThreadExecutor();
      
               //Variable length thread pool
       //        ExecutorService executorService = Executors.newCachedThreadPool();
               try{
                   for (int i = 0; i < 10; i++) {
                       executorService.execute(()->{
                           System.out.println(Thread.currentThread().getName() + " Executing!");
                           try {
                               TimeUnit.SECONDS.sleep(2);
                           } catch (InterruptedException e) {
                               e.printStackTrace();
                           }
                       });
                   }
               }catch (Exception e){
                   e.printStackTrace();
               }finally {
                   System.out.println("====================Program execution completed");
                   executorService.isShutdown();
               }
           }
       }
       ```
      

Thread pools are generally not used in the form of tool classes, but mostly in the form of customization, as shown below

public class Demo1 {

    public static void main(String[] args) {
        //Reusable fixed capacity thread pool
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        //Single threaded thread pool
//        ExecutorService executorService = Executors.newSingleThreadExecutor();

        //Variable length thread pool
//        ExecutorService executorService = Executors.newCachedThreadPool();
        try{
            for (int i = 0; i < 10; i++) {
                executorService.execute(()->{
                    System.out.println(Thread.currentThread().getName() + " Executing!");
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("====================Program execution completed");
            executorService.isShutdown();
        }
    }
}
12. Branching and merging
  • Branching and merging of threads

  • Scene simulation: add from 1 to 100. If the difference between the two numbers is greater than 10, branch. Use the binary search method to branch the values

  • 1.. . 10 11.. . . 20 . . . . 91.. . . . 100

  • Use class

  • ForkJoinPool branch merge pool

  • RecursiveTask extends ForkJoinTask

    public class Demo1 {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
    
            long startTimes1 = System.currentTimeMillis();
            MyTask2 task = new MyTask2(0, 100);
            Integer compute = task.compute();
            System.out.println(compute);
            long endTimes1 = System.currentTimeMillis();
            System.out.println("Single thread time:" + (endTimes1 - startTimes1));
    
            long startTimes = System.currentTimeMillis();
            //Create task object
            MyTask myTask = new MyTask(0, 100);
            //Create branch merge pool object
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(myTask);
            //Get final merge results
            Integer integer = forkJoinTask.get();
            System.out.println(integer);
            //Close branch merge pool
            forkJoinPool.shutdown();
            long endTimes = System.currentTimeMillis();
            System.out.println("Multithreading time:" + (endTimes - startTimes));
    
        }
    }
    
    /**
     * Task execution class
     */
    class MyTask extends RecursiveTask<Integer> {
    
        private static final Integer LIMIT = 10;
    
        private int start;
    
        private int end;
    
        private int result;
    
        public MyTask(int start,int end){
            this.start=start;
            this.end=end;
        }
    
        @Override
        protected Integer compute() {
            if((end-start)>LIMIT){
                int middle = (end+start)/2;
                MyTask myTask1 = new MyTask(start, middle);
                MyTask myTask2 = new MyTask(middle + 1, end);
    
                myTask1.fork();
                myTask2.fork();
                result = myTask1.join() + myTask2.join();
            }else {
                for (int i = start; i <=end; i++) {
                    result = result + i;
                }
            }
            return result;
        }
    }
    
    /**
     * Task execution class
     */
    class MyTask2 {
    
        private static final Integer LIMIT = 10;
    
        private Integer start;
    
        private Integer end;
    
        private Integer result;
    
        public MyTask2(Integer start,Integer end){
            this.start=start;
            this.end=end;
        }
    
        protected Integer compute() {
            if((end-start)>LIMIT){
                Integer middle = (end+start)/2;
                MyTask myTask1 = new MyTask(start, middle);
                MyTask myTask2 = new MyTask(middle + 1, end);
    
                result = myTask1.compute() + myTask2.compute();
            }else {
                for (int i = start; i <=end; i++) {
                    result = result + i;
                }
            }
            return result;
        }
    }
    

13. Asynchronous callback

The synchronization and asynchrony of threads adopt the CompletableFuture class

Asynchrony is to call the completableFuture.whenComplete().get() method, where the whenComplete parameter is a consumptive functional programming object

Where T: return value of successful asynchronous call

U: Exception information in case of exception

public class CompletableFutureDemo {

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

        CompletableFutureDemo completableFutureDemo = new CompletableFutureDemo();
//        completableFutureDemo.synchronize();
//        System.out.println("------------------------------------------------------");
        completableFutureDemo.asynchronous();

    }

    /**
     * Synchronize
     * The thread is called synchronously. When calling the completabilefuture. Get () method, the thread will block and continue to execute after the sub thread is executed
     */
    private void synchronize() throws ExecutionException, InterruptedException {
        //Synchronous call
        //runAsync synchronous call
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "Thread call!");

        });
        System.out.println("Thread execution 2");

        //Synchronous call return structure
        completableFuture.get();
        System.out.println("Thread call 3");
    }

    /**
     * asynchronous
     * whenComplete Implement asynchronous callback
     * Parameter resolution:
     *      t:Successful return value
     *      u:Failed exception information
     */
    private void asynchronous() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "Child thread call");
            return 200;
        });
        System.out.println("Thread execution 2");
        completableFuture.whenComplete((Object t,Object u)->{
            System.out.println(t);
            System.out.println(u);
        }).get();

        System.out.println("End of thread execution");
    }
}

Posted by iimrii on Thu, 04 Nov 2021 18:07:21 -0700