Java multithreading and bundled starter sample

  • 2020-04-01 02:25:21
  • OfStack

One, Java multithreading basic introduction
Java multithreaded programming is still relatively important, in the actual business development will often encounter this problem. With Java multithreading, there are two traditional ways to create threads. 1. Inherit from the Thread class and override the run method. 2. Implement Runnable interface and run method. The method that starts the thread is called the start method, and the run method is actually executed.
The reference code is as follows:


package com.jack.thread;

public class ThreadDemo1 {
    
    public static class Test1Thread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("Test1," + Thread.currentThread().getName() + ", i = " + i);
            }
        }
    }
    
    public static class Test2Thread implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("Test2," + Thread.currentThread().getName() + ", i = " + i);
            }
        }
    }
    
    public static void main(String[] args) {
        new Test1Thread().start();//Start thread 1
        new Thread(new Test2Thread()).start();//Start thread 2
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("Test3," + Thread.currentThread().getName() + ", i = " + i);
                }
            }
        }).start();//Start thread 3
    }
}

Two, Java and a simple introduction to the package
Multiple threads, unified handling of the same variable demo code:


package com.jack.thread;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadDemo2 {
    private static int count = 0;
    public static class CountThread implements Runnable {//1. There is a thread safety problem, and the Shared variables are out of order
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count++;
                System.out.println(Thread.currentThread().getName() + ", count = " + count);
            }
        }
    }
    private static final Object lock = new Object();//The lock object used here
    public static class Count2Thread implements Runnable {//This is using a mutex mode
        @Override
        public void run() {
            synchronized (lock) {//Use mutex mode
                for (int i = 0; i < 100; i++) {
                    count++;
                    System.out.println(Thread.currentThread().getName() + ", count = " + count);
                }
            }
        }
    }
    private static AtomicInteger ai = new AtomicInteger();//Here, the AtomicXXX class is used and distributed, and the CAS mode is used: compare and swap
    public static class Count3Thread implements Runnable {//AtomicInteger internal CAS implementation, using: loop, judge, set trilogy
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                int tmp = ai.incrementAndGet();//CAS is adopted for processing
                System.out.println(Thread.currentThread().getName() + ", count = " + tmp);
            }
        }
    }
    private static volatile int countV = 0;//Define volatile to make the multiple threads aware, because the values are in main memory
    public static class Count4Thread implements Runnable {//Volatile defines a variable that simply goes into main memory. The ++ operation is not an atomic operation, so be careful
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(50);//Let the thread sleep here, increasing the error probability
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                countV++;//The correct use of volatile does not mean that it is safe to define volatile, but it is important to note that ++ - operations are not atomic operations
                System.out.println(Thread.currentThread().getName() + ", count = " + countV);
            }
        }
    }
    
    public static <T> void testTemplate(T t) throws InstantiationException, IllegalAccessException, InterruptedException {
        for (int i = 0; i < 5; i++) {
            if (t instanceof Runnable) {
                Class<?> c = t.getClass();
                Object object = c.newInstance();
                new Thread((Runnable) object).start();
            }
        }
    }
    
    public static void main(String[] args) throws InterruptedException, InstantiationException, IllegalAccessException {
        //1. Test 1
        // testTemplate(new CountThread());
        //2. Test 2
        // testTemplate(new Count2Thread());
        //3. Test 3
        // testTemplate(new Count3Thread());
        //4. Test 4
        testTemplate(new Count4Thread());
        Thread.sleep(15000);
        System.out.println(count);
        System.out.println(ai.get());
        System.out.println(countV);
    }
}

Producer-consumer model
The producer (thread that produces the product) -- is responsible for producing the product consumer (thread that consumes the product) -- is responsible for consuming the product
Car buyers, consumers. People who sell cars, people who sell cars, let's call them producers. Warehouse, place where cars are stored. Car factories, places where cars are actually made.
The reference code is as follows:
// the code without synchronization mechanism is as follows:


package com.jack.thread;
import java.util.ArrayList;
import java.util.List;
import com.jack.thread.ThreadDemo3.CarBigHouse.Car;

public class ThreadDemo3 {
    
    public static class CarSeller implements Runnable {
        private CarBigHouse bigHouse;
        public CarSeller(CarBigHouse bigHouse) {
            this.bigHouse = bigHouse;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {//As the producer thread adds cars to the warehouse, it actually triggers the addition of cars
                int count = bigHouse.put();
                System.out.println(" Production car -->count = " + count);
            }
        }
    }
    
    public static class Consumer implements Runnable {
        private CarBigHouse bigHouse;
        public Consumer(CarBigHouse bigHouse) {
            this.bigHouse = bigHouse;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {//So, as a consumer thread, to extract the car from the warehouse, it's actually triggering to extract a car from the warehouse
                int count = bigHouse.get();
                System.out.println(" Automobile consumption -->count = " + count);
            }
        }
    }
    
    public static class CarBigHouse {
        public int carNums = 0;//This is the total number of cars in the warehouse
        public List<Car> carList = new ArrayList<Car>();//So let's simulate a list of cars
        public int put() {//An interface is provided to the producer to place the car in the warehouse
            Car car = CarFactory.makeNewCar();
            carList.add(car);//Add it to the warehouse
            carNums++;//Increase the total by 1
            return carNums;
        }
        public int get() {//It provides the customer with the interface to take the car from this side
            Car car = null;
            if (carList.size() != 0) {//To pick up the car when it is not empty
                car = carList.get(carList.size() - 1);//Extract the last car
                carList.remove(car);//Remove from the list of removed libraries
                carNums--;//Decrease the total by 1
            }
            return carNums;
        }
        public static class Car {
            public String carName;//Name of the car
            public double carPrice;//Car prices
            public Car() {
            }
            public Car(String carName, double carPrice) {
                this.carName = carName;
                this.carPrice = carPrice;
            }
        }
    }
    
    public static class CarFactory {
        private CarFactory() {
        }
        public static Car makeNewCar(String carName, double carPrice) {
            return new Car(carName, carPrice);
        }
        public static Car makeNewCar() {
            return new Car();
        }
    }
    
    public static void main(String[] args) {
        CarBigHouse bigHouse = new CarBigHouse();
        new Thread(new CarSeller(bigHouse)).start();
        new Thread(new Consumer(bigHouse)).start();
    }
}

// with the mutex code as follows:


package com.jack.thread;
import java.util.ArrayList;
import java.util.List;
import com.jack.thread.ThreadDemo4.CarBigHouse.Car;

public class ThreadDemo4 {
    
    public static class CarSeller implements Runnable {
        private CarBigHouse bigHouse;
        public CarSeller(CarBigHouse bigHouse) {
            this.bigHouse = bigHouse;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {//As the producer thread adds cars to the warehouse, it actually triggers the addition of cars
                int count = bigHouse.put();
                System.out.println(" Production car -->count = " + count);
            }
        }
    }
    
    public static class Consumer implements Runnable {
        private CarBigHouse bigHouse;
        public Consumer(CarBigHouse bigHouse) {
            this.bigHouse = bigHouse;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {//So, as a consumer thread, to extract the car from the warehouse, it's actually triggering to extract a car from the warehouse
                int count = bigHouse.get();
                System.out.println(" Automobile consumption -->count = " + count);
            }
        }
    }
    
    public static class CarBigHouse {
        public int carNums = 0;//This is the total number of cars in the warehouse
        public List<Car> carList = new ArrayList<Car>();//So let's simulate a list of cars

        //Add the synchronized keyword method, member method, and lock the current bigHouse object
        //This lock is a mutex, a method that only one thread can access at a time
        public synchronized int put() {//An interface is provided to the producer to place the car in the warehouse
            Car car = CarFactory.makeNewCar();
            carList.add(car);//Add it to the warehouse
            carNums++;//Increase the total by 1
            return carNums;
        }
        public synchronized int get() {//It provides the customer with the interface to take the car from this side
            Car car = null;
            if (carList.size() != 0) {//To pick up the car when it is not empty
                car = carList.get(carList.size() - 1);//Extract the last car
                carList.remove(car);//Remove from the list of removed libraries
                carNums--;//Decrease the total by 1
            }
            return carNums;
        }
        public static class Car {
            public String carName;//Name of the car
            public double carPrice;//Car prices
            public Car() {
            }
            public Car(String carName, double carPrice) {
                this.carName = carName;
                this.carPrice = carPrice;
            }
        }
    }
    
    public static class CarFactory {
        private CarFactory() {
        }
        public static Car makeNewCar(String carName, double carPrice) {
            return new Car(carName, carPrice);
        }
        public static Car makeNewCar() {
            return new Car();
        }
    }
    
    public static void main(String[] args) {
        CarBigHouse bigHouse = new CarBigHouse();
        new Thread(new CarSeller(bigHouse)).start();
        new Thread(new Consumer(bigHouse)).start();
    }
}

/ with the Object class's wait and notify or notifyAll methods (notice the difference between the notify and notifyAll methods) // notify is to wake up one of the waiting threads. // notifyAll wakes up all the other waiting threads, but it still depends on the race as to which thread gets the lock.
Thread status: create, run, block, destroy status. (there are many blocking situations, such as waiting for data IO input, which is blocked.)


package com.jack.thread;
import java.util.ArrayList;
import java.util.List;
import com.jack.thread.ThreadDemo4.CarBigHouse.Car;

public class ThreadDemo4 {
    
    public static class CarSeller implements Runnable {
        private CarBigHouse bigHouse;
        public CarSeller(CarBigHouse bigHouse) {
            this.bigHouse = bigHouse;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {//As the producer thread adds cars to the warehouse, it actually triggers the addition of cars
                int count = bigHouse.put();
                System.out.println(" Production car -->count = " + count);
            }
        }
    }
    
    public static class Consumer implements Runnable {
        private CarBigHouse bigHouse;
        public Consumer(CarBigHouse bigHouse) {
            this.bigHouse = bigHouse;
        }
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {//So, as a consumer thread, to extract the car from the warehouse, it's actually triggering to extract a car from the warehouse
                int count = bigHouse.get();
                System.out.println(" Automobile consumption -->count = " + count);
            }
        }
    }
    
    public static class CarBigHouse {
        public int carNums = 0;//This is the total number of cars in the warehouse
        public List<Car> carList = new ArrayList<Car>();//So let's simulate a list of cars
        public static final int max = 100;//Simple Settings, do the upper limit Settings
        private Object lock = new Object();//The wait and notify methods of object are adopted to handle the synchronization problem
        public int put() {//An interface is provided to the producer to place the car in the warehouse
            synchronized (lock) {
                if (carList.size() == max) {//We hit the ceiling and we don't make cars anymore
                    try {
                        lock.wait();//Block handling
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Car car = CarFactory.makeNewCar();
                carList.add(car);//Add it to the warehouse
                carNums++;//Increase the total by 1
                lock.notify();//Wakes up the waiting thread
                return carNums;
            }
        }
        public int get() {//It provides the customer with the interface to take the car from this side
            Car car = null;
            synchronized (lock) {
                if (carList.size() == 0) {//There are no cars to consume
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (carList.size() != 0) {//To pick up the car when it is not empty
                    car = carList.get(carList.size() - 1);//Extract the last car
                    carList.remove(car);//Remove from the list of removed libraries
                    carNums--;//Decrease the total by 1
                }
                lock.notify();
                return carNums;
            }
        }
        public static class Car {
            public String carName;//Name of the car
            public double carPrice;//Car prices
            public Car() {
            }
            public Car(String carName, double carPrice) {
                this.carName = carName;
                this.carPrice = carPrice;
            }
        }
    }
    
    public static class CarFactory {
        private CarFactory() {
        }
        public static Car makeNewCar(String carName, double carPrice) {
            return new Car(carName, carPrice);
        }
        public static Car makeNewCar() {
            return new Car();
        }
    }
    
    public static void main(String[] args) {
        CarBigHouse bigHouse = new CarBigHouse();
        new Thread(new CarSeller(bigHouse)).start();
        new Thread(new Consumer(bigHouse)).start();
    }
}


Related articles: