Crazy god said JUC bi bi li video link address: www.bilibili.com/video/BV1B7…
1. What is JUC
JUC is toolkits, packages, categories, etc. under java.util.
Common thread code:
- Thread
- Runnable has no return value and is relatively inefficient compared to Callable.
- Callable has a return value!
2. Threads and processes
Threads, processes, if you can’t use a one-sentence spoken technology, not solid!
- Process: a program, qi.exe music.exe program collection;
- A process can often contain multiple threads, at least one!
- Java has 2 threads by default? Mian, GC,
- Thread: opened a process Typora, write, autosave (thread responsible)
- For Java it provides:
Thread, Runnable, and Callable
Manipulate threads.
Can Java really start threads? The answer is: no!
public synchronized void start(a) {
/** * This method is not invoked for the main method thread * or "system" group threads created/set up by the VM. Any new * functionality added to this method in the future may have to * also be added to the VM.A zero status value corresponds to * state "NEW". */
if(threadStatus ! =0)
throw new IllegalThreadStateException();
/* * Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if(! started) { group.threadStartFailed(this); }}catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then it will be passed up the call stack */}}}// the local method, the underlying operation is C++, Java cannot directly manipulate the hardware
private native void start0(a);
Copy the code
Concurrent, parallel
Concurrent programming: concurrent, parallel
Concurrency (multiple threads working on the same resource)
- A core CPU, simulated out of multiple threads, fast alternating.
Parallel (more than one person walking together)
- Multi-core CPU, multiple threads can execute simultaneously; Eg: Thread pool!
public class Test1 {
public static void main(String[] args) {
// Get the number of CPU cores
// CPU intensive, IO intensive
System.out.println(Runtime.getRuntime().availableProcessors());
// If the computer has 8 cores, the result output is 8}}Copy the code
The essence of concurrent programming: Make full use of CPU resources
Threads have several states (6)
public enum State {
/** * Thread state for a Thread which has not yet started
NEW,
/** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but It may * be waiting for other resources from the operating system * such as processor
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@linkObject#wait() object.wait}. * Thread blocking status */
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@linkLockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt> thread.join ()</tt> * is waiting for a specified Thread to terminate
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@linkLockSupport#parkUntil locksupport. parkUntil}</li> * </ul> * Thread timeout wait status, after a certain amount of time will not wait */
TIMED_WAITING,
/** * Thread state for a terminated Thread. * The Thread has completed execution
TERMINATED;
}
Copy the code
Wait/sleep
1. They come from different classes
- wait => Object
- sleep => Thread
2. Release of locks
- Wait releases the lock
- Hold the lock to sleep, will not release!
3. The scope of use is different
- Wait must be used in synchronized code blocks
- Sleep can sleep anywhere
3, Synchronized lock
Traditional Synchronized lock
Let’s look at an example of multi-threaded ticket selling
package com.haust.juc01;
/* * @auther: csp1999 * @date: 2020/07/21/13:59 * @description: ticket example */
public class SaleTicketTDemo01 {
/* * A thread is a single resource class with no operations attached to it! * 1, properties, methods */
public static void main(String[] args) {
// Concurrency: multiple threads operate on a resource class at the same time, throwing the resource class into the thread
Ticket ticket = new Ticket();
// @functionalInterface, jdk1.8 lambada expression
new Thread(() -> {
for (int i = 1; i < 50; i++) { ticket.sale(); }},"A").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) { ticket.sale(); }},"B").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) { ticket.sale(); }},"C").start(); }}// Resource class OOP
class Ticket {
// Attributes, methods
private int number = 50;
// The way tickets are sold
// synchronized
public synchronized void sale(a) {
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "Sold out" +
(50-(--number)) + "One ticket, the rest :" + number + "Ticket"); }}}Copy the code
4, Lock up
The Lock interface
- Fair lock: Very fair, threads are executed in first-come-first-served order
- Unfair lock: Very unfair: Can cut in line (default lock)
Replace synchronized with lock in the ticket example above:
package com.haust.juc01;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/* * @auther: csp1999 * @date: 2020/07/21/13:59 * @description: Ticket example 2 */
public class SaleTicketTDemo02 {
public static void main(String[] args) {
// Concurrency: multiple threads operate on a resource class at the same time, throwing the resource class into the thread
Ticket2 ticket = new Ticket2();
// @functionalInterface, jdk1.8 lambada expression
new Thread(() -> {
for (int i = 1; i < 50; i++) { ticket.sale(); }},"A").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) { ticket.sale(); }},"B").start();
new Thread(() -> {
for (int i = 1; i < 50; i++) { ticket.sale(); }},"C").start(); }}/ / Lock 3 steps
// 1. new ReentrantLock();
// 2. Lock. Lock ()
// 3. Lock. Unlock (
class Ticket2 {
// Attributes, methods
private int number = 50;
Lock lock = new ReentrantLock();
// How to sell tickets
public void sale(a) {
lock.lock();/ / lock
try {
// Business code
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "Sold out" +
(50 - (--number)) + "One ticket, the rest :" + number + "Ticket"); }}catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();/ / unlock}}}Copy the code
Synchronized and Lock:
- 1, Synchronized built-in Java keyword, Lock is a Java class
- 2. Synchronized cannot determine the state of obtaining a Lock. Lock can determine whether a Lock is obtained
- 3, Synchronized will automatically release the lock, lock must be manually released lock! If the lock is not released, a deadlock occurs
- Synchronized thread 1 (acquire lock, if thread 1 blocks), thread 2 (wait, dumb, etc.) Lock will not necessarily wait;
- 5, Synchronized can re-enter the lock, can not interrupt, not fair; Lock, reentrant Lock, can judge Lock, not fair (can set themselves);
- 6, Synchronized suitable for locking a small number of code synchronization problems, Lock suitable for locking a large number of synchronization code!
What is a lock, how to determine what is locked!
This problem will be analyzed with examples later.
5. Producer and consumer issues
Common interview questions: singleton patterns, sorting algorithms, producers and consumers, deadlocks
Synchronized edition of producer and consumer issues
package com.haust.pc;
/** * Communication issues between threads: producer and consumer issues! The same variable num = 0 * A num+1 * B num-1 */
public class A {
public static void main(String[] args) {
Data data = new Data();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch(InterruptedException e) { e.printStackTrace(); }}},"A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch(InterruptedException e) { e.printStackTrace(); }}},"B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch(InterruptedException e) { e.printStackTrace(); }}},"C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch(InterruptedException e) { e.printStackTrace(); }}},"D").start(); }}// Determine wait, business, notification
class Data { // Digital resource class
private int number = 0;
/ / + 1
public synchronized void increment(a) throws InterruptedException {
Increment (); increment(); increment(); increment(); increment(); increment() If =0, a. wait() waits (wait() releases the lock), and C tries to execute the production method, but still checks number! =0, then b. wait() waits (wait() releases the lock). It happens that the consumer thread B/D consumes a product, making number=0, and then calls this.notifyall () after B/D consumes; The producer thread continues to wait(), and the consumer calls this.notifyall (). The producer thread waits () and the consumer calls this.notifyall (). Producers then continue to produce ahead of themselves, eventually leading to 'excess capacity', where number is greater than 1 if(number! = 0){// wait this.wait(); } * /
while(number ! =0) { // Note that you can't use "if" or false wake up will occur
/ / wait for
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "= >" + number);
// Notify other threads that I +1 is done
this.notifyAll();
}
/ / 1
public synchronized void decrement(a) throws InterruptedException {
while (number == 0) {
/ / wait for
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "= >" + number);
// Notify other threads that I am done with -1
this.notifyAll(); }}Copy the code
There is A problem, A B C D 4 threads! False awaken
First go to the java.lang package of the CHM documentation to find Object, and then go to the wait() method:
Therefore, while judgment must be used in the above code, not if
JUC edition of producer and consumer issues
Condition is found by Lock in the official documentation
Click on Condition to check
Code implementation:
package com.haust.pc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/** * Communication issues between threads: producer and consumer issues! The same variable num = 0 * A num+1 * B num-1 */
public class B {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch(InterruptedException e) { e.printStackTrace(); }}},"A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch(InterruptedException e) { e.printStackTrace(); }}},"B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch(InterruptedException e) { e.printStackTrace(); }}},"C").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch(InterruptedException e) { e.printStackTrace(); }}},"D").start(); }}// Determine wait, business, notification
class Data2 { // Digital resource class
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//condition.await(); / / wait for
//condition.signalAll(); // Wake up all
/ / + 1
public void increment(a) throws InterruptedException {
lock.lock();
try {
// Business code
while(number ! =0) {
/ / wait for
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + "= >" + number);
// Notify other threads that I +1 is done
condition.signal();
}catch (Exception e){
e.printStackTrace();
}finally{ lock.unlock(); }}/ / 1
public void decrement(a) throws InterruptedException {
lock.lock();
try {
while (number == 0) {
/ / wait for
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName() + "= >" + number);
// Notify other threads that I am done with -1
condition.signal();
}catch (Exception e){
e.printStackTrace();
}finally{ lock.unlock(); }}}Copy the code
Any new technology does not just cover the original technology, it has its advantages and complement to the old technology!
Condition notifies and wakes up threads precisely
The running results of the above code are shown as follows:
Question: The order of ABCD thread preemption is random. How can we improve the code if we want ABCD threads to execute in order?
Code implementation:
package com.haust.pc;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/* * A calls B, B calls C, and C calls A */
public class C {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(() -> {
for (int i = 0; i < 10; i++) { data.printA(); }},"A").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) { data.printB(); }},"B").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) { data.printC(); }},"C").start(); }}class Data3 { // Resource class Lock
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1;
// number=1 A number=2 B Number =3 C
public void printA(a) {
lock.lock();
try {
// Business, judge -> execute -> notify
while(number ! =1) {
/ / A wait
condition1.await();
}
System.out.println(Thread.currentThread().getName() + "=>AAAAAAA");
// Wake up the specified person, B
number = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally{ lock.unlock(); }}public void printB(a) {
lock.lock();
try {
// Business, judge -> execute -> notify
while(number ! =2) {
/ / wait for B
condition2.await();
}
System.out.println(Thread.currentThread().getName() + "=>BBBBBBBBB");
// Wake up the specified person, c
number = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally{ lock.unlock(); }}public void printC(a) {
lock.lock();
try {
// Business, judge -> execute -> notify
// Business, judge -> execute -> notify
while(number ! =3) {
/ / C waiting
condition3.await();
}
System.out.println(Thread.currentThread().getName() + "=>CCCCC ");
// Wake up the specified person, A
number = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally{ lock.unlock(); }}}Copy the code
Test results:
6. 8 Locking
Put forward a problem in front: how to judge who is locked! Know what a lock is and who the lock is!
Deep understanding of our locks
The object of a synchronized lock is the caller of a method
Code Example 1:
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
1, Under standard conditions, two lines print first send SMS or print first make a phone call? 1, sendSms delay 4 seconds, two lines print first sendSms or call? 1/ Text message 2/ call */.
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
// The lock exists
new Thread(()->{
phone.sendSms();
},"A").start();
/ / capture
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start(); }}class Phone{
// Synchronized lock objects are method callers! ,
// Both methods are called with the same object (the same lock). Whoever gets the lock first executes it!
public synchronized void sendSms(a){
try {
TimeUnit.SECONDS.sleep(4);// Hold the lock to sleep
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Texting");
}
public synchronized void call(a){
System.out.println("Make a call"); }}// Send SMS messages first, then make phone calls
Copy the code
Normal method has no lock! If the method is not synchronized, it is not affected by the lock and executes normally
Code Example 2:
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
/** * 3, add a normal method after! SMS or Hello first? // Common methods * 4, two objects, two synchronization methods, SMS or call? // Call */
public class Test2 {
public static void main(String[] args) {
// Two objects, two callers, two locks!
Phone2 phone1 = new Phone2();
Phone2 phone2 = new Phone2();
// The lock exists
new Thread(()->{
phone1.sendSms();
},"A").start();
/ / capture
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
new Thread(()->{
phone2.hello();
},"C").start(); }}class Phone2{
// Synchronized lock objects are method callers!
public synchronized void sendSms(a){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Texting");
}
public synchronized void call(a){
System.out.println("Make a call");
}
// There is no lock here! Non-synchronous methods are not affected by locks
public void hello(a){
System.out.println("hello"); }}// Make a call first, then hello, and finally send a message
Copy the code
** There is only one Class template for each instance of an object
Code Example 3:
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
/** * 5, add two static synchronization methods, only one object, print first send SMS? Make a phone call? * 6, Two objects! Add two static synchronization methods, print first and send SMS? Make a phone call? * /
public class Test3 {
public static void main(String[] args) {
// There is only one Class template for two objects
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
// The lock exists
new Thread(()->{
phone1.sendSms();
},"A").start();
/ / capture
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start(); }}// Phone3 has a unique Class object
class Phone3{
// Synchronized lock objects are method callers!
// static static method
// The class is available as soon as it is loaded. Lock is a Class
public static synchronized void sendSms(a){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Texting");
}
public static synchronized void call(a){
System.out.println("Make a call"); }}// Send SMS messages first, then make phone calls
Copy the code
Code Example 4:
package com.haust.lock8;
import java.util.concurrent.TimeUnit;
/** * 7, 1 static synchronization method, 1 normal synchronization method, 1 object, print first send SMS? Make a phone call? * 8, 1 static synchronization method, 1 ordinary synchronization method, two objects, first print SMS? Make a phone call? * /
public class Test4 {
public static void main(String[] args) {
// There is only one Class template for two objects
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
// The lock exists
new Thread(()->{
phone1.sendSms();
},"A").start();
/ / capture
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start(); }}// Phone3 has a unique Class object
class Phone4{
// Static synchronized methods lock Class templates
public static synchronized void sendSms(a){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Texting");
}
// The caller (object) of a normal synchronized method lock, which has a different object, so there is no need to wait
public synchronized void call(a){
System.out.println("Make a call"); }}// 7/8 In both cases, the phone call is executed first and the SMS message is executed later, because the objects of the two locks are different.
// Static synchronization locks the Class template. Normal synchronization locks the instantiated object.
// Instead of waiting for the former to unlock before the latter can be executed, the two can be executed in parallel because SMS sleep lasts for 4s
// So call first.
Copy the code
summary
- New This Specifies a mobile phone
- Static Class unique template
7. Collection classes are unsafe
The List is not safe
* * List, ArrayList, and so on under the condition of simultaneous multi-threading, cannot realize data sharing, when multiple threads at the same time call a List object will appear abnormal ConcurrentModificationException concurrent modification * *.
Code examples:
package com.haust.unsafe;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/ / Java. Util. ConcurrentModificationException concurrent modification exception!
public class ListTest {
public static void main(String[] args) {
// Synchronized;
/* * Solution; List
List = new Vector<>(); * scheme 2, a List < String > List = * Collections in synchronizedList (new ArrayList < > ()); List
List = new CopyOnWriteArrayList<>(); * /
/* CopyOnWrite An optimization strategy in computer programming for copy-on-write; * Fixed, write (overwrite) when read by multiple threads * Avoid overwrite when written, causing data problems! Where is CopyOnWriteArrayList more than Vector Nb? * /
List<String> list = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0.5)); System.out.println(list); },String.valueOf(i)).start(); }}}Copy the code
CopyOnWriteArrayList source code analysis reference
The Set is not safe
* * the Set, the Hash, etc under the condition of simultaneous multi-threading, cannot realize data sharing, when multiple threads at the same time call a Set object will appear abnormal ConcurrentModificationException concurrent modification * *.
Code examples:
package com.haust.unsafe;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** * Abnormal ConcurrentModificationException concurrent modification * 1, Set the < String > Set = * Collections. SynchronizedSet (new HashSet < > ()); *, *, / 2
public class SetTest {
public static void main(String[] args) {
//Set
set = new HashSet<>(); / / not safe
// Set
set = Collections.synchronizedSet(new HashSet<>()); / / security
Set<String> set = new CopyOnWriteArraySet<>();/ / security
for (int i = 1; i <=30 ; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString().substring(0.5)); System.out.println(set); },String.valueOf(i)).start(); }}}Copy the code
Extension: What is underneath a hashSet?
You can see that the underlying HashSet is a HashMap
HashMap source code analysis reference
The Map is not safe
Review the basic Map operations:
Code examples:
package com.haust.unsafe;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
// ConcurrentModificationException
public class MapTest {
public static void main(String[] args) {
// Is map used in this way? No, we don't use hashMaps at work
// What is the default equivalent? New HashMap < > (16,0.75);
// Map<String, String> map = new HashMap<>();
// Extension: Investigate the principle of ConcurrentHashMap
Map<String, String> map = new ConcurrentHashMap<>();
for (int i = 1; i <=30; i++) {
new Thread(()->{
map.put(Thread.currentThread().getName(),
UUID.randomUUID().toString().substring(0.5)); System.out.println(map); },String.valueOf(i)).start(); }}}Copy the code
8. Callable (simple)
Callable vs. Runable:
For example, if Callable is you and you want to meet your girlfriend **Runable **, her best friend Thread
- Callable is an interface under Concurrent under the java.util package that returns a value and can throw checked exceptions
- Runable is an interface under the java.lang package that returns no value and cannot throw checked exceptions
- Run ()/ call()
The difference between Lock and Synchronized is that the former is an interface under java.util and the latter is a keyword under java.lang.
The code for
package com.haust.callable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/** * 1, ** * 2, */
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// new Thread(new Runnable()).start(); / / start a Runnable
// new Thread(new FutureTask<V>()).start();
// new Thread(new FutureTask<V>( Callable )).start();
new Thread().start(); // How to start Callable?
// new an instance of MyThread
MyThread thread = new MyThread();
// The MyThread instance goes into FutureTask
FutureTask futureTask = new FutureTask(thread); / / class
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start(); // The call() method results are cached for efficiency, so only one call is printed
// The get method may block! Put him to the end
Integer o = (Integer) futureTask.get();
// Or use asynchronous communication to handle!
System.out.println(o);/ / 1024}}class MyThread implements Callable<Integer> {
@Override
public Integer call(a) {
System.out.println("call()"); // How many calls do threads A and B print? (1)
// Time-consuming operation
return 1024; }}//class MyThread implements Runnable {
//
// @Override
// public void run() {
// System.out.println("run()"); // Prints several runs
/ /}
/ /}
Copy the code
Details:
1. Cache
Results may need to wait, will block!
9. Commonly used auxiliary classes (must)
9.1, CountDownLatch
Subtraction counter: implementation calls a thread several times before firing a task
Code examples:
package com.haust.add;
import java.util.concurrent.CountDownLatch;
/ / counter
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
// The total number is 6, the task must be executed, then use!
CountDownLatch countDownLatch = new CountDownLatch(6);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()
+" Go out");
countDownLatch.countDown(); / / the number 1
},String.valueOf(i)).start();
}
countDownLatch.await(); // Wait for the counter to zero, and then proceed down
System.out.println("Close Door"); }}Copy the code
Principle:
countDownLatch.countDown(); / / the number 1
countDownLatch.await(); // Wait for the counter to zero, and then proceed down
Every time a thread calls countDown() countdownlatch.await (), countdownlatch.await () will be woken up, assuming the counter goes to 0, and continue!
9.2, CyclicBarrier
Add counter: Collect 7 dragon balls to summon the divine dragon
Code examples:
package com.haust.add;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
/* * Collect 7 dragon balls to summon the dragon */
// Summon dragon ball thread
CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
System.out.println("Summon the Dragon successfully!");
});
for (int i = 1; i <=7 ; i++) {
final int temp = i;
// Can lambda operate on I
new Thread(()->{
System.out.println(Thread.currentThread().getName()
+"Collect"+temp+"Dragon Ball");
try {
cyclicBarrier.await(); / / wait for
} catch (InterruptedException e) {
e.printStackTrace();
} catch(BrokenBarrierException e) { e.printStackTrace(); } }).start(); }}}Copy the code
9.3, Semaphore
Semaphore: Semaphore
Limit traffic/grab parking space! 6 cars — 3 parking Spaces
Code examples:
package com.haust.add;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class SemaphoreDemo {
public static void main(String[] args) {
// Number of threads: parking Spaces! Current limit! ,
// If there are 3 threads executing (3 Spaces are full), the other threads need to wait for the 'parking space' to be released before executing!
Semaphore semaphore = new Semaphore(3);
for (int i = 1; i <=6 ; i++) {
new Thread(()->{
/ / acquire ()
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(); / / release ()} },String.valueOf(i)).start(); }}}Copy the code
There are only three parking Spaces, and the next car can park there only when one car leaves and the space becomes vacant.
The output result is shown as follows:
Principle:
semaphore.acquire(); Get, assuming if already full, wait, wait to be released! semaphore.release(); Release, which releases the current semaphore + 1 and wakes up the waiting thread!
Function: Multiple shared resources mutually exclusive use! Concurrency limit, control the maximum number of threads!
10. ReadWriteLock
ReadWriteLock
Code examples:
package com.haust.rw;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/** * Exclusive lock (write lock) can only be held by one thread at a time * Shared lock (read lock) Multiple threads can hold at the same time * ReadWriteLock * Read - Read can coexist! * Read-write cannot coexist! * Write - Write cannot coexist! * /
public class ReadWriteLockDemo {
public static void main(String[] args) {
//MyCache myCache = new MyCache();
MyCacheLock myCacheLock = new MyCacheLock();
/ / write
for (int i = 1; i <= 5 ; i++) {
final int temp = i;
new Thread(()->{
myCacheLock.put(temp+"",temp+"");
},String.valueOf(i)).start();
}
/ / read
for (int i = 1; i <= 5 ; i++) {
final int temp = i;
new Thread(()->{
myCacheLock.get(temp+""); },String.valueOf(i)).start(); }}}/** * Custom cache * lock */
class MyCacheLock{
private volatile Map<String,Object> map = new HashMap<>();
// Read/write locks: more fine-grained control
private ReadWriteLock readWriteLock = new
ReentrantReadWriteLock();
// private Lock lock = new ReentrantLock();
// When writing, only one thread is expected to write simultaneously
public void put(String key,Object value){
readWriteLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+"Written"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()
+"Write" OK "to");
} catch (Exception e) {
e.printStackTrace();
} finally{ readWriteLock.writeLock().unlock(); }}// Take, read, anyone can read!
public void get(String key){
readWriteLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+"Read"+key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName()
+Read "OK");
} catch (Exception e) {
e.printStackTrace();
} finally{ readWriteLock.readLock().unlock(); }}}/** * Custom cache * unlocked */
class MyCache{
private volatile Map<String,Object> map = new HashMap<>();
/ / save, write
public void put(String key,Object value){
System.out.println(Thread.currentThread().getName()
+"Written"+key);
map.put(key,value);
System.out.println(Thread.currentThread().getName()
+"Write" OK "to");
}
/ / get read
public void get(String key){
System.out.println(Thread.currentThread().getName()
+"Read"+key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName()
+Read "OK"); }}Copy the code
The execution effect is shown as follows:
Block the queue
Blocking queue:
BlockingQueue
BlockingQueue is not new
When do we use blocking queues? : multi-threaded concurrent processing, thread pool with more!
Learn to use queues
Add, Remove
Four groups of API
way | An exception is thrown | Return value, no exception thrown | Block waiting for | Timeout waiting for |
---|---|---|---|---|
add | add | offer() | put() | offer(,) |
remove | remove | poll() | take() | poll(,) |
Detects the head element of the queue | element | peek() | – | – |
Code examples:
package com.kuang.bq;
import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) throws InterruptedException {
test4();
}
/** * 1. No return value, exception method */
public static void test1(a){
// Queue size
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.add("a"));// true
System.out.println(blockingQueue.add("b"));// true
System.out.println(blockingQueue.add("c"));// true
// System.out.println(blockingQueue.add("d"));
// IllegalStateException: Queue Full Throws an exception -- the Queue is full!
System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = =");
System.out.println(blockingQueue.element());//
// check who the team leader element is
System.out.println(blockingQueue.remove());//
System.out.println(blockingQueue.remove());//
System.out.println(blockingQueue.remove());//
// System.out.println(blockingQueue.remove());
/ / Java. Util. NoSuchElementException throws an exception - the queue is empty!
}
/** * 2. Returns a value without throwing an exception */
public static void test2(a){
// Queue size
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.peek());
// System.out.println(blockingQueue.offer("d"));
// false does not throw an exception!
System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = =");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
// null does not throw an exception!
}
/** * 3. Wait, block (always block) */
public static void test3(a) throws InterruptedException {
// Queue size
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
// block all the time
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
// blockingQueue.put("d"); // The queue runs out of space
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
// Without this element, block and wait
}
/** * 4. Wait, block (wait timeout) */
public static void test4(a) throws InterruptedException {
// Queue size
ArrayBlockingQueue blockingQueue =
new ArrayBlockingQueue<>(3);
blockingQueue.offer("a");
blockingQueue.offer("b");
blockingQueue.offer("c");
// blockingQueue.offer("d",2,TimeUnit.SECONDS);
// Wait more than 2 seconds to exit
System.out.println("= = = = = = = = = = = = = = =");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
blockingQueue.poll(2,TimeUnit.SECONDS); // Wait more than 2 seconds to exit}}Copy the code
SynchronousQueue
SynchronousQueue SynchronousQueue
There is no capacity, an element in, must wait to take out, can put another element in!
Put, take
Code examples:
package com.haust.bq;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
SynchronousQueue: Unlike other BlockingQueues, SynchronousQueue does not store elements. A SynchronousQueue must take an element from it before it can be put in. * /
public class SynchronousQueueDemo {
public static void main(String[] args) {
BlockingQueue<String> blockingQueue =
new SynchronousQueue<>(); // Synchronize the queue
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()
+" put 1");
// put enters an element
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName()
+" put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName()
+" put 3");
blockingQueue.put("3");
} catch(InterruptedException e) { e.printStackTrace(); }},"T1").start();
new Thread(()->{
try {
// Sleep 3s takes an element
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()
+"= >"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()
+"= >"+blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()
+"= >"+blockingQueue.take());
} catch(InterruptedException e) { e.printStackTrace(); }},"T2").start(); }}Copy the code
The execution result is as follows:
12. Thread Pools (emphasis)
Thread pool: 3 methods, 7 parameters, 4 rejection policies
Pooling technology
The operation of the program, the essence: occupy the resources of the system! (Optimize resource usage => pooling technique)
Thread pool, connection pool, memory pool, object pool Create and destroy. A waste of resources
Pooling technology: prepare some resources in advance, and if someone wants to use them, come to me to take them and return them to me after using them.
Benefits of thread pools:
- 1. Reduce system resource consumption
- 2, improve the speed of response
- 3, convenient management
Thread reuse, can control the maximum number of concurrent, management threads
Thread pools: 3 big methods
Thread pools: 3 big methods
Sample code:
package com.haust.pool;
import java.util.concurrent.ExecutorService;
import java.util.List;
import java.util.concurrent.Executors;
public class Demo01 {
public static void main(String[] args) {
// Executors Tools, 3 major methods
// Executors.newSingleThreadExecutor(); // Create a single thread pool
// Executors.newFixedThreadPool(5); // Create a thread pool of fixed size
// Executors.newCachedThreadPool(); // Create a scalable thread pool
// A thread pool for a single thread
ExecutorService threadPool =
Executors.newSingleThreadExecutor();
try {
for (int i = 1; i < 100; i++) {
// After using thread pools, use thread pools to create threads
threadPool.execute(()->{
System.out.println(
Thread.currentThread().getName()+" ok"); }); }}catch (Exception e) {
e.printStackTrace();
} finally {
// The thread pool is used up, the program ends, close the thread poolthreadPool.shutdown(); }}}Copy the code
Thread pool: 7 parameters
Seven parameters
Source code analysis:
public static ExecutorService newSingleThreadExecutor(a) {
return new FinalizableDelegatedExecutorService (
new ThreadPoolExecutor(
1.1.0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(
5.5.0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool(a) {
return new ThreadPoolExecutor(
0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
ThreadPoolExecutor ()
public ThreadPoolExecutor(intCorePoolSize, // Core thread pool sizeintMaximumPoolSize, // Maximum core thread pool sizelongBlockingQueue<Runnable> workQueue, // Thread factory: ThreadFactory ThreadFactory // RejectedExecutionHandler Handle) {
if (corePoolSize < 0
|| maximumPoolSize <= 0
|| maximumPoolSize < corePoolSize
|| keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null
|| threadFactory == null
|| handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null
? null : AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
Copy the code
Create a thread pool manually
Manually create a thread pool and customize 7 parameters for the tool Executors. Procedure
Sample code:
package com.haust.pool;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
// Executors Tools, 3 major methods
// Executors.newSingleThreadExecutor(); // Create a single thread pool
// Executors.newFixedThreadPool(5); // Create a thread pool of fixed size
// Executors.newCachedThreadPool(); // Create a scalable thread pool
/** * Four rejection strategies: * * * new ThreadPoolExecutor. AbortPolicy () the bank is full, the others to come in, don't deal with this person, Throw an exception * * new ThreadPoolExecutor. CallerRunsPolicy () * which come of where to go! Such as your father let you to notify the mother to wash clothes, mother refused, let you go back to notify dad wash * * new ThreadPoolExecutor. DiscardPolicy () * queue is full, the task he lost never throw an exception. * * * new ThreadPoolExecutor. DiscardOldestPolicy () queue is full, the attempt to and the first competition, also won't throw an exception! * /
public class Demo01 {
public static void main(String[] args) {
// Custom thread pool! Work ThreadPoolExecutor
ExecutorService threadPool = new ThreadPoolExecutor(
2.// int corePoolSize, size of the core thread pool
5.// int maximumPoolSize, the maximum size of the core thread pool
3.// long keepAliveTime, timeout 3 seconds no one call will be released, put close window
TimeUnit.SECONDS,// TimeUnit unit, timeout unit in seconds
new LinkedBlockingDeque<>(3),// Block queue (maximum 3 people in waiting area)
Executors.defaultThreadFactory(),// Default thread factory
// One of the four rejection strategies:
// When the queue is full, try to compete with the earliest one without throwing an exception!
new ThreadPoolExecutor.DiscardOldestPolicy());
// When the queue is full, try to compete with the earliest one without throwing an exception!
try {
// Max load: Deque + Max
/ / than RejectedExecutionException
for (int i = 1; i <= 9; i++) {
// After using thread pools, use thread pools to create threads
threadPool.execute(()->{
System.out.println(
Thread.currentThread().getName()+" ok"); }); }}catch (Exception e) {
e.printStackTrace();
} finally {
// The thread pool is used up, the program ends, close the thread poolthreadPool.shutdown(); }}}Copy the code
Thread pool: four rejection policies
Four rejection strategies
/** * Four rejection strategies: * * * new ThreadPoolExecutor. AbortPolicy () the bank is full, the others to come in, don't deal with this person, Throw an exception * * new ThreadPoolExecutor. CallerRunsPolicy () * which come of where to go! Such as your father let you to notify the mother to wash clothes, mother refused, let you go back to notify dad wash * * new ThreadPoolExecutor. DiscardPolicy () * queue is full, the task he lost never throw an exception. * * * new ThreadPoolExecutor. DiscardOldestPolicy () queue is full, the attempt to and the first competition, also won't throw an exception! * /
Copy the code
Summary and expansion
How to set the maximum pool capacity!
Understand: IO intensive, CPU intensive: (tuning)
Directly on the code:
package com.haust.pool;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class Demo01 {
public static void main(String[] args) {
// Custom thread pool! Work ThreadPoolExecutor
// How to define the maximum thread
// 1, CPU intensive, a few cores, just a few, can maintain the highest efficiency of CPU!
// 2, IO intensive > determine your application is very IO intensive thread,
// For example, the program has 15 large tasks.
// Set the IO intensive parameter (maximum number of threads) to greater than 15
// Get the number of CPU cores
System.out.println(
Runtime.getRuntime().availableProcessors());/ / 8 cores
ExecutorService threadPool = new ThreadPoolExecutor(
2.// int corePoolSize, the core thread pool size
// int maximumPoolSize, the maximum thread pool size for an 8-core computer is 8
Runtime.getRuntime().availableProcessors(),
3.// long keepAliveTime, which is released when no one calls it after 3 seconds
TimeUnit.SECONDS,// TimeUnit unit, timeout unit in seconds
new LinkedBlockingDeque<>(3),// Block queue (maximum 3 people in waiting area)
Executors.defaultThreadFactory(),// Default thread factory
// One of the four rejection strategies:
// When the queue is full, try to compete with the earliest one without throwing an exception!
new ThreadPoolExecutor.DiscardOldestPolicy());
// When the queue is full, try to compete with the earliest one without throwing an exception!
try {
// Max load: Deque + Max
/ / than RejectedExecutionException
for (int i = 1; i <= 9; i++) {
// After using thread pools, use thread pools to create threads
threadPool.execute(()->{
System.out.println(
Thread.currentThread().getName()+" ok"); }); }}catch (Exception e) {
e.printStackTrace();
} finally {
// The thread pool is used up, the program ends, close the thread poolthreadPool.shutdown(); }}}Copy the code