JUC concurrent programming

1. What is JUC

  • The purpose of concurrent programming is to make full use of CPU resources to improve program performance
  • java.util.concurrent (a tool class for java Concurrent Programming)

2, thread

  • Process: for example, every application opened by our computer

  • Thread: a process contains at least one thread, and there are at least two threads in java: main and gc

  • Concurrency: the process of multiple threads operating a resource class alternately

  • Parallel: in the case of multi-core CPUs, each CPU can execute a thread at the same time, and do not preempt each other's CPU resources

  • Thread state

  • NEW: the thread status of a thread that has not been started

  • RUNNABLE: the thread state of a RUNNABLE thread

  • BLOCKED: the thread status of the BLOCKED thread waiting for the monitor lock

  • WAITING: WAITING for the thread state of the thread

  • Timed "waiting: the thread state of a waiting thread with a specified waiting time

  • TERMINATED: the thread state of the TERMINATED thread. Thread has completed execution

  • The difference between wait and sleep?

    • class

      • wait > method of object
      • Sleep – > thread method (if A calls the sleep method of B, then A is sleeping)
    • Whether to release the lock

      • Sleep: sleep with lock
      • wait: locks will be released
    • Scope of use

      • wait/notify/notifyAll can only be used in synchronization methods or synchronization blocks
      • sleep can be used anywhere
    • abnormal

      • Both need to catch InterruptedException exception

3. The difference between synchronized and lock

  • Synchronized is a keyword, java is built-in, and Lock is a java class
  • Synchronized can't judge whether the Lock is obtained, Lock can judge
  • Synchronized will automatically release the lock. Lock needs to release the lock in finally (if not released, it will deadlock. Multiple locks () require multiple unlocks ())
  • Synchronized one thread is blocked, and other threads have to wait forever. Lock can try to obtain the lock through tryLock(), and end the wait if the lock is not obtained
  • Synchronized re-entry (you can enter the bedroom or toilet after entering the door), non interruptible, unfair, Lock re-entry, interruptible, fair and unfair (the structure supports manual setting of fairness or unfairness)
    • Fairness: need to line up, must come first
    • Unfair: queue jumping (benefit: increased efficiency, e.g. no need to wait for threads with long execution time)

synchronized code

/**
 * High cohesion of attribute methods (do not implement runnable interface directly in resource class)
 */
public class SaleTicket {
    private int number =30;

    public synchronized void sale(){
        if(number>0){
            System.out.println(Thread.currentThread().getName()+"Sold the first"+(number--)+"Tickets left"+number+"Zhang ticket");
        }
    }
}

/**
 * Multithreaded programming routine:
 * 1.High cohesion and low coupling (premise)
 * 2.Thread operation (method of external exposure of resource class) resource class (key point)
 *
 *
 * 3 30 tickets for each conductor
 */
class Test{
    public static void main(String[] args) {
        SaleTicket saleTicket = new SaleTicket();

        new Thread(()->{
            for (int i = 1; i <= 30; i++) {
                saleTicket.sale();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 1; i <= 30; i++) {
                saleTicket.sale();
            }
        },"B").start();
        new Thread(()->{
            for (int i = 1; i <= 30; i++) {
                saleTicket.sale();
            }
        },"C").start();
    }
}

Lock code

/**
 * High cohesion of attribute methods (do not implement runnable interface directly in resource class)
 */
public class SaleTicket2 {
    private int number =40;
    private Lock lock = new ReentrantLock();
    public void sale(){
        lock.lock();
        try {
            if(number>0){
                System.out.println(Thread.currentThread().getName()+"Sold the first"+(number--)+"Tickets left"+number+"Zhang ticket");
            }
        } finally {
            lock.unlock();
        }
    }
}

/**
 * Multithreaded programming routine:
 * 1.High cohesion and low coupling (premise)
 * 2.Thread operation (method of external exposure of resource class) resource class (key point)
 *
 * 3 40 tickets for each conductor
 */
class Test2{
    public static void main(String[] args) {
        SaleTicket2 saleTicket = new SaleTicket2();

        new Thread(()->{
            for (int i = 1; i <= 40; i++) {
                saleTicket.sale();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 1; i <= 40; i++) {
                saleTicket.sale();
            }
        },"B").start();
        new Thread(()->{
            for (int i = 1; i <= 40; i++) {
                saleTicket.sale();
            }
        },"C").start();
    }
}
  • Producer and consumer: judge work notice (threads cannot communicate with each other, so threads need to be scheduled)

Synchronized producer consumer code (including false wake-up processing)

/**
 * Title: two threads operate a variable with an initial value of 0
 *      One thread + one thread - 1 judge when + 1 and when - 1
 *      Alternate 10 times
 *
 *  Multithreaded programming routine:
 *  * 1.High cohesion and low coupling (premise)
 *  * 2.Thread operation (method of external exposure of resource class) resource class (key point)
 *
 *  Producer consumer model: judge work notice
 */
public class Test {

    public static void main(String[] args) {
        Data data = new Data();

        new Thread(()->{
            for (int i = 1; i <= 10; i++) {
                try {
                    data.incrementNum();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(()->{
            for (int i = 1; i <= 10; i++) {
                try {
                    data.decrementNum();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

        new Thread(()->{
            for (int i = 1; i <= 10; i++) {
                try {
                    data.decrementNum();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();

        new Thread(()->{
            for (int i = 1; i <= 10; i++) {
                try {
                    data.decrementNum();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"D").start();
    }
}
class Data{ 
	   private int num =0 ; 
       //+1
       public synchronized void incrementNum() throws InterruptedException{
           //judge
           /*if(num!=0){//False wake-up
               this.wait();
           }*/
           while(num!=0){ //while prevents false wakeup
               this.wait();
           }
           //work
           num++;
           System.out.println(Thread.currentThread().getName()+"\t"+num);
   
           //notice
           this.notifyAll();
       }
   
       //-1
       public synchronized void decrementNum() throws InterruptedException{
           //judge
           /*if(num==0){ False wake-up
               this.wait();
           }*/
           while(num==0){//while prevents false wakeup
               this.wait();
           }
           //work
           num--;
           System.out.println(Thread.currentThread().getName()+"\t"+num);
   
           //notice
           this.notifyAll();
       }
   }

Lock version producer consumer (including accurate wake-up)

/**
 * Three threads A B C
  * Three threads print in turn
  * A 5 second
  * B 10 second
  * C 15 second
  * Cycle in turn
  *
  * Accurate wake up through num logo
  */
 public class C {
 
     public static void main(String[] args) {
         Data3 data3 = new Data3();
 
         new Thread(()->{
             data3.print5();
         },"A").start();
         new Thread(()->{
             data3.print10();
         },"B").start();
         new Thread(()->{
             data3.print15();
         },"C").start();
     }
 
 }
 class Data3{
     private int num =1 ;
     private Lock lock = new ReentrantLock();
     private Condition condition1 = lock.newCondition();
     private Condition condition2 = lock.newCondition();
     private Condition condition3 = lock.newCondition();
 
     public  void print5(){
         lock.lock();
         try {
             //judge
             while(num!=1){ //while prevents false wakeup
                 condition1.await();
             }
             //work
             for (int i = 1; i <= 5; i++) {
                 System.out.println(Thread.currentThread().getName()+"\t"+i);
             }
             num=2;
 
             //Notify the second thread to work (specify the thread to work)
             condition2.signal();
         }catch (InterruptedException e){
             e.printStackTrace();
         }finally {
             lock.unlock();
         }
     }
     public  void print10(){
         lock.lock();
         try {
             //judge
             while(num!=2){ //while prevents false wakeup
           condition2.await();
             }
          //work
             for (int i = 1; i <= 10; i++) {
              System.out.println(Thread.currentThread().getName()+"\t"+i);
             }
          num=3;
 
             //Notify the third thread to work (specify the thread to work)
             condition3.signal();
         }catch (InterruptedException e){
             e.printStackTrace();
         } finally {
             lock.unlock();
         }
     }
     public  void print15(){
         lock.lock();
         try {
             //judge
             while(num!=3){ //while prevents false wakeup
                 condition3.await();
             }
             //work
             for (int i = 1; i <= 15; i++) {
                 System.out.println(Thread.currentThread().getName()+"\t"+i);
             }
             num=1;
 
             //Notify the first thread to work (specify the thread to work)
             condition1.signal();
         }catch (InterruptedException e){
             e.printStackTrace();
         } finally {
             lock.unlock();
         }
     }
 }

3. 8. Thorough understanding of lock phenomenon

1. Standard access, would you like to print email or SMS first?

/**
 * Standard access: print email or SMS first
 * 
 *  mail
 */
public class Test {
    public static void main(String[] args) {
        Phone phone = new Phone();
        //Two threads use the same object, two threads have a lock, so the first one to call is executed first
        new Thread(()->{
            phone.sendEmail();
        },"A").start();
        new Thread(()->{
            phone.sendSm();
        },"B").start();
    }
}
class Phone{

    //synchronized locks are the method's callers
    public synchronized void sendEmail(){
        System.out.println("sendEmail");
    }

    public synchronized void sendSm(){
        System.out.println("sendSm");
    }
}

2. Email method is suspended for 4 seconds. Would you like to print email or SMS first?

/**
 * **2,Email method is suspended for 4 seconds. Would you like to print email or SMS first? * *
 *
 *  mail
 */
public class Test2 {
    public static void main(String[] args) {
        Phone2 phone = new Phone2();
        //Two threads use the same object, two threads have a lock, so the first one to call is executed first
        new Thread(()->{
            phone.sendEmail();
        },"A").start();
        new Thread(()->{
            phone.sendSm();
        },"B").start();
    }
}
class Phone2{

    //synchronized locks are the method's callers
    public synchronized void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("sendEmail");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void sendSm(){
        System.out.println("sendSm");
    }
}

3. hello() is not synchronized. Would you like to print the email first or hello?

/**
 * hello() is not synchronized. Would you like to print the email first or hello?
 *
 *  hello
 */
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
     Phone3 phone = new Phone3();
        //Two threads use the same object, two threads have a lock, so the first one to call is executed first
     new Thread(()->{  //First execution
            phone.sendEmail();
        },"A").start();

        //interfere
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{  //Execute in a second
            phone.hello();
        },"B").start();
    }
}

//Lock: competitive relationship
class Phone3{

    //synchronized locks are the method's callers
    public synchronized void sendEmail(){
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("sendEmail");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void sendMS() {
        System.out.println("sendMS");
    }

    //hello is not modified by Synchronized. It is not a synchronization method, so there is no need to wait. Other threads use a lock
    public void hello(){
        System.out.println("hello");
    }
}

4. Two mobile phones, please print email or SMS first?

/**
 * Two mobile phones, please print email or SMS first?
 * 
 * Short message
 *
 */
public class Test4 {

    //Like: go home and enter the bedroom (lock) bathroom respectively
   public static void main(String[] args) throws InterruptedException {
        //Two objects, no interference with each other
     Phone4 phone1 = new Phone4();
        Phone4 phone2 = new Phone4();

        new Thread(()->{  //From the beginning
            phone1.sendEmail();
        },"A").start();

        //interfere
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{  //Execute in a second
            phone2.sendMS();
        },"B").start();
    }
}

//Lock: competitive relationship
class Phone4{

    //A method decorated with synchronized. The object of the lock is the caller of the method,
    // If the callers are different, there is no relationship between them. The two methods are not the same lock
    public synchronized void sendEmail(){
        //It's lovely to say that there's a kind delay
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("sendEmail");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void sendMS() {
        System.out.println("sendMS");
    }
}

5. Two static synchronization methods, the same mobile phone, please print email or SMS first?

/**
 * Two static synchronization methods, the same mobile phone, please print email or SMS first?
 *
 * mail
 *
 */
public class Test5 {

    //Like: go home and enter the bedroom (lock) bathroom respectively
    public static void main(String[] args) throws InterruptedException {
     //Two objects, no interference with each other
        Phone5 phone1 = new Phone5();

        new Thread(()->{  //From the beginning
            phone1.sendEmail();
        },"A").start();

        //interfere
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{  //Execute in a second
            phone1.sendMS();
        },"B").start();
    }
}

class Phone5{

    //Object class template can be used for many new objects
    //There is only one class template

    //Methods decorated with synchronized and static. The lock object is the only class object of the class
    //Same lock
    public static synchronized void sendEmail(){
        //It's lovely to say that there's a kind delay
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("sendEmail");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static synchronized void sendMS() {
        System.out.println("sendMS");
    }
}

6. Two static synchronization methods, two mobile phones. Would you like to print email or SMS first?

/**
 * Two static synchronization methods, two mobile phones. Would you like to print email or SMS first?
 *
 * mail
 *
 */
public class Test6 {

    //Like: go home and enter the bedroom (lock) bathroom respectively
    public static void main(String[] args) throws InterruptedException {
        //Two objects, the same class template and the same lock, so the first to call is to execute
     Phone6 phone1 = new Phone6();
        Phone6 phone2 = new Phone6();

        new Thread(()->{  //From the beginning
            phone1.sendEmail();
        },"A").start();

        //interfere
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{  //Execute in a second
            phone2.sendMS();
        },"B").start();
    }
}


class Phone6{

    //Object class template can be used for many new objects
    //There is only one class template

    //Methods decorated with synchronized and static. The lock object is the only class object of the class
    //Same lock
    public static synchronized void sendEmail(){
        //It's lovely to say that there's a kind delay
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("sendEmail");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static synchronized void sendMS() {
        System.out.println("sendMS");
    }
}

7, A common synchronization method, a static synchronization method, the same mobile phone, would you like to print mail or SMS first?

/**
 * A common synchronization method, a static synchronization method and the same mobile phone. Would you like to print email or SMS first?
 *
 * SMS (object inconsistency, class lock and object lock do not interfere with each other)
 *
 */
public class Test7 {

    //Like: go home and enter the bedroom (lock) bathroom respectively
 public static void main(String[] args) throws InterruptedException {
        //Two objects, no interference with each other
        Phone7 phone1 = new Phone7();

        new Thread(()->{  //From the beginning
            phone1.sendEmail();
        },"A").start();

        //interfere
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{  //Execute in a second
            phone1.sendMS();
        },"B").start();
    }
}


class Phone7{

   //CLASS
    public static synchronized void sendEmail(){
        //It's lovely to say that there's a kind delay
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("sendEmail");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //object
    public synchronized void sendMS() {
        System.out.println("sendMS");
    }
}

8. A common synchronization method, a static synchronization method and two mobile phones. Would you like to print email or SMS first?

/**
 * A common synchronization method, a static synchronization method and two mobile phones. Would you like to print email or SMS first?
 *
 * SMS (object inconsistency, class lock and object lock do not interfere with each other)
 *
 */
public class Test8 {

 //Like: go home and enter the bedroom (lock) bathroom respectively
    public static void main(String[] args) throws InterruptedException {
     //Two objects, no interference with each other
        Phone7 phone1 = new Phone7();
     Phone7 phone2 = new Phone7();

     new Thread(()->{  //From the beginning
            phone1.sendEmail();
     },"A").start();

     //interfere
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{  //Execute in a second
            phone1.sendMS();
        },"B").start();
    }
}


class Phone8{

   //CLASS
    public static synchronized void sendEmail(){
        //It's lovely to say that there's a kind delay
        try {
            TimeUnit.SECONDS.sleep(2);
            System.out.println("sendEmail");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //object
    public synchronized void sendMS() {
        System.out.println("sendMS");
    }
}

Summary

  1. This object of new this itself, caller
  2. Static class template, unique!
  3. There are multiple synchronized methods in an object. If there is only one thread accessing the synchronized method at a certain time, it will be locked, independent public toilet! Other threads will block!
  4. After adding a common method, two objects have no priority, one is locked and the other is unlocked! Things will change!
  5. Change to static synchronization method, the situation will change! class, the lock of all static synchronization methods is unique. The lock is the object instance class itself!

4. Collection class is not safe

List: single thread safe, multi thread unsafe

  • Single thread
package com.coding.collunsafe;

import java.util.Arrays;
import java.util.List;

public class UnsafeList1 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("a", "b", "c");
        list.forEach(System.out::println);
    }
}
  • Multithreading
package com.coding.unsafe;

import java.util.*;

/**
 * Good at summarizing:
 *  1.Fault phenomenon
 *  2.Cause
 *  3.Solution
 *
 */
public class UnsafeList2 {

    public static void main(String[] args) {

        //code implementation
        ////High efficiency does not support concurrency (add method is not locked)
        ArrayList<String> list = new ArrayList<>();

        // Test whether the list is safe under multithreading
        //An exception will be generated under unsafe multithreading: ConcurrentModificationException


        for (int i = 1; i <= 300; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,4));
                System.out.println(list);
            }).start();
        }
    }
}
  • List multithreading unsafe solution
package com.coding.unsafe;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Good at summarizing:
 *  1.Fault phenomenon
 *  2.Cause
 *  3.Solution
 *
 */
public class UnsafeList3 {

    public static void main(String[] args) {

        //code implementation
        ////High efficiency does not support concurrency (add method is not locked)
        //ArrayList<String> list = new ArrayList<>();
        // Thread safe class is inefficient (add method uses lock)
       // List<String> list = new Vector<>();  50
       // List<String> list = Collections.synchronizedList(new ArrayList());  60

        //Write time replication in multithreaded high concurrency programming, consistency is the most important
        //If read without lock
        //If you are writing, you should copy one to yourself and put it back after modification
        List<String> list = new CopyOnWriteArrayList<>();


        // Test whether the list is safe under multithreading
        //An exception will be generated under unsafe multithreading: ConcurrentModificationException


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

Set

package com.coding.unsafe;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

public class UnsafeSet {

    public static void main(String[] args) {
        Set<String> hashSet = new HashSet<>();//What's at the bottom? new HashMap
        for (int i = 1; i <= 30; i++) {//Multithreading will report ConcurrentModificationException
            new Thread(()->{
                hashSet.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(hashSet);
            },String.valueOf(i)).start();
        }
    }
}
  • Set multi thread unsafe solution
package com.coding.unsafe;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;

public class SafeSet {

    public static void main(String[] args) {
        //First method 60 points
        //Set<Object> hashSet = Collections.synchronizedSet(new HashSet<>());

        //The second method 100 points
        Set<String> hashSet = new CopyOnWriteArraySet<>();
        for (int i = 1; i <= 300; i++) {//Multithreading will report ConcurrentModificationException
            new Thread(()->{
                hashSet.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(hashSet);
            },String.valueOf(i)).start();
        }
    }
}

Map

package com.coding.unsafe;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class UnsafeMap {
    public static void main(String[] args) {
        Map<String, Object> hashMap = new HashMap<>();
        //The initial capacity loading factor is the same as the following
        //Map<String, Object> hashMap = new HashMap<>(16, 0.75F);
        for (int i = 1; i <= 300; i++) {//Multithreading will report ConcurrentModificationException
            new Thread(()->{
                hashMap.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,5));
                System.out.println(hashMap);
            },String.valueOf(i)).start();
        }

    }
}

  • Solution to unsafe multi thread of Map
package com.coding.unsafe;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class SafeMap {
    public static void main(String[] args) {

        //The first method, coding teacher jdk1.8, does not
        //Map<String, Object> hashMap = Collections.synchronizedMap(new HashMap<>());

        //The second method
        Map<Object, Object> hashMap = new ConcurrentHashMap<>();


        for (int i = 1; i <= 300; i++) {
            new Thread(()->{
                hashMap.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0,5));
                System.out.println(hashMap);
            },String.valueOf(i)).start();
        }

    }
}

5,Callable

  • Thread creation method: difference between thread, Runnable and Callable
    • Whether there is a return value
    • Whether to throw an exception (when calling task. Get(), it needs to throw: ExecutionException, InterruptedException)
    • Different methods: run(), call()
package com.coding.callableDemo;

import com.coding.demo02.A;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

public class Test1 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //new Thread(Runnable)
        //new Thread(RunnableFuture)
        //new Thread(FutureTask)

        //new Thread(new A(),"A").start();
        FutureTask<Integer> task = new FutureTask<>(new B());

        new Thread(task,"A").start();//Two threads still output one result
        new Thread(task,"B").start();//Detail 1: result cache, N times more efficient

        System.out.println(task.get());//Get results
        //Detail 2: get() is generally placed at the end to ensure the efficiency of smooth operation of the result, because it will block waiting for the result to be generated
        //When the thread takes time and the result return is not important

    }
}

/*class A implements Runnable{
    @Override
    public void run() {
        System.out.println("Runnable");
    }
}*/

class B implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("Callable");

        TimeUnit.SECONDS.sleep(10);
        return 1024;
    }
}
Published 1 original article, won praise 1, visited 13
Private letter follow

Tags: Java Mobile Programming Attribute

Posted on Sat, 07 Mar 2020 05:17:41 -0500 by agoni