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
,>
,>
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