Concurrent Programming in Java - Complete notes on the basics advanced Advanced.Copy the code

This is not know how many times brush crazy god JUC concurrent programming, from the first confusion to now more clear, is a big progress, before the JUC notes disappeared, make a new set of notes.

Refer to the link: www.bilibili.com/video/BV1B7…


1. Multithreading — Basics

  • 1. The Thread state
  • 2.Synchronized
  • 3. Lock the Lock
  • 4. To summarize

β˜•οΈ 2. Synchronized

  • 1.synchronized
  • 2.static synchronized

3.Java Collections — Security

High concurrency – helper classes

  • 1.countdownLatch
  • 2.cyclicbarrier
  • 3.semaphore

5 ReadWriteLock

6 the thread pool

  • 1. Collections — queues (blocking queues, synchronization queues)
  • 2. Basic concepts of thread pool (three methods, seven parameters, four rejection strategies)

7.Stream(4 functional interfaces, Lambda, asynchronous callback)

  • 1. Functional interfaces
  • 2. Lambda expressions
  • 3. Asynchronous callback

8. Singleton mode

  • 1. Hungry mode (new as soon as the program starts, it takes up a lot of memory)
  • 2. Lazy mode (DCL mode: dual detection, only new when needed)

9. Volatile and Atomic

10. Lock in Java

  • 1. Fair Lock (FIFO) : Synchronized Lock can be customized
  • 2. Unfair Lock (allows queue-jumping):Lock Lock can be customized
  • 3. Reentrant locks (acquiring one lock and acquiring another does not cause a deadlock) :lock and synchronized
  • 4. Spin locks: Wait until you can’t get them
  • 5. Check the deadlock command




πŸ”₯1. Multithreading — Basics

1. The Thread state

6: New, Run, block, wait, timeout wait, end (click on Thread to view the source code)

public enum State {
        NEW,

        RUNNABLE,

        BLOCKED,

        WAITING,

        TIMED_WAITING,

        TERMINATED;
    }
Copy the code


2.Synchronized
  • Not fair lock
  • Reentrant lock,

Synchronized: Non-fair locking (the order in which a thread acquires a lock cannot be guaranteed, that is, threads will not queue up to acquire the resource but will scramble for it, but the result must be correct); reentrant locking (having acquired a lock, it can acquire another lock without causing a deadlock, for example, synchronized can write a synchronized function inside)

    /** * Author: HuYuQiao * Description: Synchronized
    class TicketSync{
        public int number = 50;
        //synchronized is essentially a queue
        public synchronized void sale(a){
            if(number > 0) {
                System.out.println(Thread.currentThread().getName() + "Got the number one." + number-- +"Ticket"); }}}Copy the code


3. Lock the Lock
  • Reentrant lock

  • Fair or unfair lock can be set (default unfair lock)

        /**
         * Creates an instance of {@code ReentrantLock} with the
         * given fairness policy.
         *
         * @param fair {@code true} if this lock should use a fair ordering policy
         */
        public ReentrantLock(boolean fair) {
            sync = fair ? new FairSync() : new NonfairSync();
        }
    Copy the code

    Lock: the Lock must be unlocked, otherwise no other thread can get it, so use a try-catch-finally.

    /** * Author: HuYuQiao * Description: Lock */
    class TicketLock{
        Lock lock = new ReentrantLock();
        public int number = 50;
        public void sale(a){
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "Got the number one." + number-- +"Ticket");

            } catch (Exception e) {
                e.printStackTrace();
            } finally{ lock.unlock(); }}}Copy the code


4. To summarize

In the case of not locking, multiple threads will scramble, resulting in inconsistent output order and calculation results. (Example: If the result is the same because there are only three threads, the for loop will fail because the number function itself is not thread-safe), so the concept of synchronized is introduced. Lock ensures the consistency of output sequence and calculation results.

False wake up: When a thread is woken up by synchronized. Wait and lock.condition. Await, it starts running after the await code, so in order to ensure that the thread can be woken up, the code needs to be included with a while statement.

The complete code

package com.empirefree.springboot;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import sun.security.krb5.internal.Ticket;

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

/ * * *@program: springboot
 * @description: Multithreading *@author: huyuqiao
 * @create: 2021/06/26 14:26 * /

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class ThreadTest {
    
    /** * Author: HuYuQiao * Description: Synchronized
    class TicketSync{
        public int number = 50;
        //synchronized is essentially a queue
        public synchronized void sale(a){
            System.out.println(Thread.currentThread().getName() + "Got the number one." + number-- +"Ticket"); }}/** * Author: HuYuQiao * Description: Lock */
    class TicketLock{
        Lock lock = new ReentrantLock();
        public int number = 50;
        public void sale(a){
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "Got the number one." + number-- +"Ticket");

            } catch (Exception e) {
                e.printStackTrace();
            } finally{ lock.unlock(); }}}@Test
    public void testThread(a) {
// TicketSync ticket = new TicketSync();
        TicketLock ticket = new TicketLock();
        new Thread( () ->{
            for (int i = 0; i < 50; i++) { ticket.sale(); }},"ThreadA").start();
        new Thread(()->{
            for (int i = 0; i < 50; i++) { ticket.sale(); }},"ThreadB").start();
        new Thread(()->{
            for (int i = 0; i < 50; i++) { ticket.sale(); }},"ThreadC").start();

        for (int i = 0; i < 500; i++) {
            newThread(() -> { ticket.sale(); }).start(); }}}Copy the code




πŸ”₯2. Synchronized

Synchronized, static modified function, execution sequence, output results.

The results show that:

1. Synchronized modified functions: Lock objects (think of methods in the lock object), so it appears that the code executes sequentially, while methods that do not lock are not affected and execute first

2. Static synchronized modified functions: lock the class. Class (the same function can be accessed by different objects), so the two objects access their own functions sequentially.

If the lock is static and the lock is not static: if the lock is static and the lock is not static: if the lock is static and the lock is not static, the lock is not static.

1.synchronized

Modifiers ensure that the same objects are executed in sequence ()

class Phone{
    //synchronized
    public synchronized void sendSms(a) {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendSms");
    }
    public synchronized  void call(a) {
        System.out.println("call");
    }

    public void playGame(a){
        System.out.println("playGame"); }}public static void main(String[] args) {
        //Thread-- Code execution order problem
        Phone phone = new Phone();
        new Thread(phone::sendSms, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(phone::call, "B").start();
        new Thread(phone::playGame, "C").start();
    }
Copy the code


2.static synchronized
class PhoneStatic{
    //static synchronized
    public static synchronized void sendSmsStatic(a) {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("sendSmsStatic");
    }
    public static synchronized  void callStatic(a) {
        System.out.println("callStatic"); }}public static void main(String[] args) {
        PhoneStatic phoneStatic = new PhoneStatic();
        PhoneStatic phoneStatic2 = new PhoneStatic();
        new Thread(() ->{
            phoneStatic2.sendSmsStatic();
        }, "A").start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() ->{
            phoneStatic2.callStatic();
        }, "B").start();
    }
Copy the code




πŸ”₯3.Java Collections — Security

        List
      
        list = new Vector<>(); List
       
         list = Collections.synchronizedList(new ArrayList<>()); List
        
          list = new CopyOnWriteArrayList<>(); Map
         
           objectObjectHashMap = new ConcurrentHashMap<>(); Map
          
            objectObjectHashMap1 = Collections.synchronizedMap(new HashMap<>()); / / set the bottom is the map: whether hashset or linkedhashset set < String > set = Collections. SynchronizedSet (new linkedhashset < > ()); Set
           
             set = new CopyOnWriteArraySet<>();
           
          ,>
         ,>
        
       
      
Copy the code




πŸ”₯4. High concurrency — helper classes

Learning links: www.cnblogs.com/meditation5…

1.countdownLatch

Countdownlatch: Subtract one until it reaches zero and then continue

package Kuangshen.JUC.Thread;import java.util.concurrent.CountDownLatch;public class countDownLatch {    public static void main(String[] args) throws InterruptedException {        final CountDownLatch countDownLatch = new CountDownLatch(5);        for (int i = 0; i < 5; i++) {            new Thread(() -> {                System.out.println(Thread.currentThread().getName() + "get out");                countDownLatch.countDown();                }, String.valueOf(i)).start();        }        countDownLatch.await(); Println ("close door"); system.out. println("close door"); }}
Copy the code


2.cyclicbarrier

Cyclicbarrier: +1 operation, for each thread automatically +1 and wait, accumulate to a specified value before executing down,

package Kuangshen.JUC.Thread;import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;/ * * *@author: Empirefree *@description: * TODO@date: 2021/2/10 10:56 * /public class cyclicbarrier {    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {        CyclicBarrier + runnable final CyclicBarrier CyclicBarrier = new CyclicBarrier(7, () ->{system.out.println (" increment to 7 is backward, as opposed to countdownlatch "); }); /* For (int I = 0, int I = 0, int I = 0, int I = 0; i < 7; i++) { int finalI = i; new Thread(() ->{ System.out.println(finalI); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } }).start(); }}}
Copy the code


3.semaphore

Semaphore: For specified values, only specified values can be obtained by multiple threads. Each acquisition must be finally released, ensuring mutually exclusive execution

package Kuangshen.JUC.Thread;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;/ * * *@author: Empirefree *@description: * TODO@date: 2021/2/10 and * /public class semaphore {    public static void main(String[] args) {        final Semaphore semaphore = new Semaphore(3);        for (int i = 0; i < 60; i++) {            new Thread(() -> {                try {                    semaphore.acquire();                    System.out.println(Thread.currentThread().getName() + "Grab a parking space.");                    TimeUnit.SECONDS.sleep(2);                    System.out.println(Thread.currentThread().getName() + "Leave the parking space.");                } catch (InterruptedException e) {                    e.printStackTrace();                } finally{ semaphore.release(); } }).start(); }}}Copy the code




πŸ”₯5. ReadWriteLock

ReadWriteLock is also a locking method for multithreading. The following lists the ways that ReadWriteLock and synchronized implement writing in multithreading

MyCache MyCache = new MyCache(); MyCache = new MyCache(); int num = 6; for (int i = 1; i < num; i++) { int finalI = i; new Thread(()->{ myCache.write(String.valueOf(finalI),String.valueOf(finalI)); },String.valueOf(i)).start(); }for (int i = 1; i < num; i++) { int finalI = i; new Thread(()->{ myCache.read(String.valueOf(finalI)); },String.valueOf(i)).start(); }class MyCache{ private volatile Map
      
        map = new HashMap<>(); private ReadWriteLock lock = new ReentrantReadWriteLock(); Public void write(String key,String value){lock.writeLock().lock(); // Write lock try {system.out.println (thread.currentThread ().getName()+" Thread start writing "); map.put(key,value); System.out.println(thread.currentThread ().getName()+" Thread starts writing OK "); } catch (Exception e){ e.printStackTrace(); } finally { lock.writeLock().unlock(); Public void read(String key){lock.readLock().lock(); // Read lock try {system.out.println (thread.currentThread ().getName()+" Thread start reading "); map.get(key); System.out.println(thread.currentThread ().getName()+" Thread read OK "); } catch (Exception e){ e.printStackTrace(); } finally { lock.readLock().unlock(); }} // save, Public synchronized void writeSync(String key,String value){try { System.out.println(thread.currentThread ().getName()+" Thread start writing "); map.put(key,value); System.out.println(thread.currentThread ().getName()+" Thread starts writing OK "); } catch (Exception e){ e.printStackTrace(); Public void readSync(String key){try {system.out.println (thread.currentThread ().getName()+" Thread start reading "); map.get(key); System.out.println(thread.currentThread ().getName()+" Thread read OK "); } catch (Exception e){ e.printStackTrace(); }}}
      ,string>
Copy the code




πŸ”₯ 6. Thread pool

1. Collections — queues (blocking queues, synchronization queues)

  • Block queue: blockingQueue (timeout wait — discard, so size=1)

            ArrayBlockingQueue
            
              ArrayBlockingQueue = new ArrayBlockingQueue<>(1); arrayBlockingQueue.offer("a", 2, TimeUnit.SECONDS); arrayBlockingQueue.offer("a", 2, TimeUnit.SECONDS); System.out.println(" Timeout wait ==" + arrayBlockingQueue.size());
            
    Copy the code
  • Synchronous queue: synchronizeQueue (similar to producer consumer)

            SynchronousQueue
            
              SynchronousQueue = new SynchronousQueue<>(); new Thread(()->{ try { System.out.println(Thread.currentThread().getName()+"put 01"); synchronousQueue.put("1"); System.out.println(Thread.currentThread().getName()+"put 02"); synchronousQueue.put("2"); System.out.println(Thread.currentThread().getName()+"put 03"); synchronousQueue.put("3"); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); new Thread(()->{ try { System.out.println(Thread.currentThread().getName()+"take"+synchronousQueue.take()); System.out.println(Thread.currentThread().getName()+"take"+synchronousQueue.take()); System.out.println(Thread.currentThread().getName()+"take"+synchronousQueue.take()); } catch (InterruptedException e) { e.printStackTrace(); } }).start();
            
    Copy the code


2. Basic concepts of thread pool (three methods, seven parameters, four rejection strategies)
  • Three methods: newSingleThreadExecutro(single thread),newFixedThreadPool(fixed size thread pool), and newCachedThreadPool(scalable)

     ExecutorService threadPool = Executors.newSingleThreadExecutor();        ExecutorService threadPool2 = Executors.newFixedThreadPool(5);        ExecutorService threadPool3 = Executors.newCachedThreadPool();
    Copy the code
  • Seven parameters:

    ThreadPoolExecutor(int corePoolSize,  Long keepAliveTime, //(maximum lifetime of idle threads: That is, if there are idle threads in the maximum thread pool, the threads will be released after this time. BlockingQueue
            
              workQueue, // Block ThreadFactory ThreadFactory, RejectedExecutionHandler Handler // Reject the policy
            
    Copy the code
  • Four rejection strategies:

    new ThreadPoolExecutor.AbortPolicy: / / the refuse strategy is: the bank is full, the others to come in, don't deal with the people, and an exception is thrown. New ThreadPoolExecutor CallerRunsPolicy () : / / / / this rejection policies for: which come of where to go to the main thread for processing new ThreadPoolExecutor. DiscardPolicy () : / / this rejection policies for: the queue is full, throw away the exception, not throw an exception. New ThreadPoolExecutor. DiscardOldestPolicy () : / / this rejection policies for: the queue is full, try to compete with the first process, not an exception
    Copy the code




πŸ”₯ 7.stream (4 functional interfaces, Lambda, asynchronous callback)

1. Functional interfaces

Learning links: www.cnblogs.com/meditation5…


2. Lambda expressions

Learning links: www.cnblogs.com/meditation5…


3. Asynchronous callback
        / / an asynchronous callback - no return value CompletableFuture < Void > future. = CompletableFuture runAsync (() - > {try {TimeUnit. SECONDS. Sleep (2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "...." ); }); System.out.println("begin"); System.out.println(future.get()); System.out.println("end"); / / an asynchronous callback, returns a value CompletableFuture < Integer > future2. = CompletableFuture supplyAsync (() - > {try {TimeUnit. SECONDS. Sleep (2); } catch (InterruptedException e) { e.printStackTrace(); } return 3; }); System.out.println("begin"); System.out.println(future2.get()); Println (future2.whenComplete((result, error) ->{system.out. println(" return result :" + result); System.out.println(" error result "+ error); }).exceptionally(throwable -> { System.out.println(throwable.getMessage()); return 502; }).get()); System.out.println("end");
Copy the code




πŸ”₯8. Singleton mode

1. Hungry mode (new as soon as the program starts, it takes up a lot of memory)
/ * * *@program: untitled * @description: singleton mode *@author: huyuqiao * @create: 2021/06/27 14:44 */public class SingleModel {    /*     * ε―θƒ½δΌšζ΅ͺθ΄Ήη©Ίι—΄     * */    private byte[] data1 = new byte[1024*1024];    private byte[] data2 = new byte[1024*1024];    private byte[] data3 = new byte[1024*1024];    private byte[] data4 = new byte[1024*1024];    private static final SingleModel hugrySingle = new SingleModel();    private SingleModel(a){}public static SingleModel getInstance(a){        return hugrySingle;    }}
Copy the code


2. Lazy mode (DCL mode: dual detection, only new when needed)

2. If the internal new object directive is rearranged, some threads will think that lazyManModel has an object, so they will return lazyManModel(null) 3. Valitile is needed to prevent instruction reordering

/ * * *@program: untitled * @description: lazy *@author: huyuqiao * @create: 2021/06/27 15:06 * /public class LazyManModel {    private volatile static LazyManModel lazyManModel;    private LazyManModel(a){        System.out.println(Thread.currentThread().getName() + "...");    }    //DCL: double check lock -- to achieve the effect, only null, otherwise not null, so need 2 if judgment. public static LazyManModel getInstance(){ if (lazyManModel == null){ synchronized (LazyManModel.class){ if (lazyManModel  == null){ lazyManModel = new LazyManModel(); } } } return lazyManModel; } public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Thread(() ->{ LazyManModel.getInstance(); }).start(); }}}
Copy the code




πŸ”₯ 9. Volatile and Atomic

Learning notes: www.cnblogs.com/meditation5…

​

πŸ”₯ 10. Java in the lock

1. Fair Lock (FIFO) : Synchronized Lock can be customized
2. Unfair Lock (allows queue-jumping):Lock Lock can be customized
3. Reentrant locks (acquiring one lock and acquiring another does not cause a deadlock) :lock and synchronized
4. Spin locks: Wait until you can’t get them
import java.util.Collections;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;import java.util.concurrent.atomic.AtomicReference;import java.util.concurrent.locks.ReentrantLock;/ * * *@program: untitled * @description: spinlock * @author: huyuqiao * @create: 2021/06/27 double-break * /public class SpinLockTest {    public static void main(String[] args) throws InterruptedException {        SpinlockDemo =new SpinlockDemo(); new Thread(()->{ spinlockDemo.myLock(); try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { spinlockDemo.myUnlock(); } },"t1").start(); TimeUnit.SECONDS.sleep(1); new Thread(()->{ spinlockDemo.myLock(); try { TimeUnit.SECONDS.sleep(3); } catch (Exception e) { e.printStackTrace(); } finally { spinlockDemo.myUnlock(); } },"t2").start(); }class SpinlockDemo {// default // int 0 //thread null AtomicReference< thread > AtomicReference =new AtomicReference<>(); Public void myLock(){Thread Thread = thread.currentThread (); System.out.println(thread.getName()+"===> mylock"); // Spin lock -- returns true if null, false if not atomicReference.compareAndSet(null,thread)){ System.out.println(Thread.currentThread().getName()+" ==> . Spin ~ "); Public void myUnlock(){Thread Thread = thread.currentThread (); System.out.println(thread.getName()+"===> myUnlock"); atomicReference.compareAndSet(thread,null); }}
Copy the code
5. Check the deadlock command
Jps-ljstack Indicates the process IDCopy the code