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
* -
- 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"); } }