Multithreading
The difference between concurrency and parallelism:
Concurrency: a single core CPU handles multiple things at the same time,
Parallelism: multi-core CPU s process multiple things at the same time.
1. Four creation methods of multithreading
- Integrated Thread class
- Implement the Runable interface
- Implement Callable interface
- Thread pool creation
Runnable and Callable Differences between runnable run Method has no return value, callable call Method has a return value runnable run Method can only throw runtime exceptions, callable call Method can capture exception information
1.1 four creation methods of thread pool
- newFixThreadPool
- newCachedThreadPool
- newScheduledThreadPool
- Newthreadpoolexecuted (custom thread pool)
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler); #Parameter description corePoolSize: Number of core threads maximumPoolSize: Maximum number of threads keepAliveTime: survival time unit: Survival unit workQueue: Blocking queue handler: Reject strategy ## Reject policy: the default is to throw an exception directly 1. AbortPolicy: Throw exception 2. CallRunsPolicy: Only the thread of the caller is used to process the task 3. DiscurdOldestPlicy: When the queue is full, discard the latest task in the queue to execute the latest task 4. DisCardPolicy: If the queue is full, it will be discarded without processing
1.2 how to set the maximum number of threads in the custom thread pool
- IO intensive: judge the amount of IO consumed in your program (assuming that there are 15 large tasks in your program and IO takes up a lot of resources. Just set the maximum number of threads > 15)
- CPU intensive: check how many cores your CPU is. (number of threads obtained in the program: runtime. Getruntime() availableProcessores() )
2. State in thread (6 states)
2.1 six states of threads
- Freshmen (NEW)
- Run (RUNNABLE)
- BLOCKED
- TIMED_WAITING
- Waiting
- Destroyed
2.2 thread state analysis
3. Common methods in threads
method | remarks |
---|---|
setPriority() | Set the priority of the thread. 0 = = "10", the higher the priority, the higher the possibility of being executed |
sleep() | Let the current thread sleep. Each thread has a lock. Sleep will not release the lock |
join() | Wait for the thread to stop |
yiled() | Release the CPU time slice, let the thread enter the ready state, and re compete for the CPU time slice |
interupt() | Interrupt thread |
deamon() | Daemon thread: (virtual machines don't have to wait for the daemon thread to end) |
3.1 what is the difference between sleep and wait methods?
- wait is a method of the Object class, and sleep is a static method of the Thread class Thread
- wait does not need to catch exceptions, sleep needs to catch exceptions
- Wait releases the lock, sleep does not. The wait method requires notify. NotifyAll wakes up. The notify method wakes up a thread randomly.
- The call location of wait can only be in the synchronous code block, and sleep can be called anywhere
3.2 what is the difference between the submit() and execute() methods in the thread pool?
- The received parameters are different
- sumbit() has a return value, but execute does not
- submit is convenient for exception processing
4. Locks in multithreading
4.1 Synchronized lock
Analysis of Synchronize lock object:
- Static method: the static method synchronize locks the Class
- Instance method: the synchronize lock is the calling object of the method
- Code block: you can arbitrarily specify whether to lock a Class template or a specific object
4.2 Lock lock
private Lock lock = new ReentrantLock(); lock.lock(); lock.unlock();
4.3 difference between synchronized and Lock
- The Java Synchronized keyword is a built-in Java Lock class
- Synchronized cannot judge the status of obtaining the lock. Lock can judge whether the lock has been obtained
- Synchronized can release the Lock automatically, and the Lock needs to be released manually (no release will cause deadlock)
5. Case analysis of producers and consumers
5.1 Synchronized producer consumer issues
Milk boxes public class Box { //Define a member variable that represents the x-th bottle of milk private int milk; //Define a member variable to represent the shape of the milk box private boolean state = false; //Provides operations for storing and obtaining milk public synchronized void put(int milk) { //If there is milk, wait for consumption if(state){ try{ wait();//wait for }catch (InterruptedException e){ e.printStackTrace(); } } //If there is no milk, produce milk this.milk = milk; System.out.println("The milkman will"+this.milk+"Put the bottle of milk into the milk box"); //After production, modify the milk box status state = true; //Wake up other waiting threads notifyAll(); } public synchronized void get(){ //If there is no milk, wait for production if(!state){ try{ wait(); }catch (InterruptedException e){ e.printStackTrace(); } } //If there is milk, consume it System.out.println("The user gets the second"+this.milk+"Bottle milk"); //After consuming milk, modify the milk box status state = false; //Wake up other waiting threads notifyAll(); } } //producer public class Producer implements Runnable { private Box b; public Producer(Box b) { this.b = b; } @Override public void run() { for(int i=1;i<=5;i++){ b.put(i);//The milkman put milk into the milk box } } } //consumer public class Customer implements Runnable { private Box b; public Customer(Box b) { this.b = b; } @Override public void run() { while (true){ b.get();//Get milk } } } public class BaS { public static void main(String[] args) { Box box = new Box();//Milk box Producer p = new Producer(box);//Producer object Customer c = new Customer(box);//Consumer object //Create two thread objects and pass the producer object and consumer object as construction method parameters respectively Thread t1 = new Thread(p); Thread t2 = new Thread(c); //Start thread t1.start(); t2.start(); } }
5.2 false wakeup of threads
package com.example.testmodule; /** * Four threads are used to simulate the false wake-up problem * A,C Threads are added * B,D Threads are reduced * wait()Method releases the lock * A The thread calls wait() to release the lock. Therefore, the C thread can also get the lock and enter the code block. At this time, Num in A and C = 0; After notifyAll() wakes up, * num + + will be performed at the same time, which will cause the quantity not to change as required. num = 2 * To solve the problem of false wake-up: you need to change the if judgment to the while judgment. */ public class test { public static void main(String[] args) { Box box = new Box(); Thread thread1 = new Thread(() -> { for (int i = 0; i < 50; i++) { try { box.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "A"); Thread thread2 = new Thread(() -> { for (int i = 0; i < 50; i++) { try { box.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "B"); Thread thread3 = new Thread(() -> { for (int i = 0; i < 50; i++) { try { box.increment(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "C"); Thread thread4 = new Thread(() -> { for (int i = 0; i < 50; i++) { try { box.decrement(); } catch (InterruptedException e) { e.printStackTrace(); } } }, "D"); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } } class Box { public int num; public synchronized void increment() throws InterruptedException { if (num != 0) { // while (num != 0){ this.wait(); } System.out.println("put:" + num++ + " have:" + num); notifyAll(); } public synchronized void decrement() throws InterruptedException { if (num == 0) { //while (num == 0){ this.wait(); } System.out.println("get:" + num-- + " have:" + num); notifyAll(); } } # Simulation results put:0 have:1 get:1 have:0 put:0 have:1 get:1 have:0 get:0 have:-1 get:-1 have:-2 get:-2 have:-3 get:-3 have:-4 get:-4 have:-5 get:-5 have:-6 .......
5.3 Lock producer consumer issues
package com.wddongtt.wddong.manyThread; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Box { //Define a member variable that represents the x-th bottle of milk private int milk; //Define a member variable to represent the shape of the milk box private boolean state = false; private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); //Provides operations for storing and obtaining milk public void put(int milk) { try { lock.lock(); //If there is milk, wait for consumption while(state){ try{ condition.await();//wait for }catch (InterruptedException e){ e.printStackTrace(); } } //If there is no milk, produce milk this.milk = milk; System.out.println("The milkman will"+this.milk+"Put the bottle of milk into the milk box"); //After production, modify the milk box status state = true; //Wake up other waiting threads condition.signalAll(); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } } public void get(){ try { lock.lock(); //If there is no milk, wait for production while(!state){ try{ condition.await(); }catch (InterruptedException e){ e.printStackTrace(); } } //If there is milk, consume it System.out.println("The user gets the second"+this.milk+"Bottle milk"); //After consuming milk, modify the milk box status state = false; //Wake up other waiting threads condition.signalAll(); }catch (Exception e){ }finally { lock.unlock(); } } } //producer class Producer implements Runnable { private Box b; public Producer(Box b) { this.b = b; } @Override public void run() { for(int i=1;i<=5;i++){ b.put(i);//The milkman put milk into the milk box } } } //consumer class Customer implements Runnable { private Box b; public Customer(Box b) { this.b = b; } @Override public void run() { while (true){ b.get();//Get milk } } } class BaS { public static void main(String[] args) { Box box = new Box();//Milk boxes Producer p = new Producer(box);//Producer object Customer c = new Customer(box);//Consumer object //Create two thread objects and pass the producer object and consumer object as construction method parameters respectively Thread t1 = new Thread(p); Thread t2 = new Thread(c); //Start thread t1.start(); t2.start(); } }
5.4 precise wake-up of Condition in lock
The advantage of LOCK over Synchronize is that LOCK can wake up accurately.
Sleep and wake in LOCK
- Sleep: await()
- Wake up: signal(),signalAll()
#Precise notification and wake-up threads package com.sjmp.demo02PC; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * A -> B -> C -> A * @description: */ public class ConditionDemo { public static void main(String[] args) { Data3 data3 = new Data3(); new Thread(()->{ for (int i = 0; i < 10; i++) { data3.printA(); } },"A").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { data3.printB(); } },"B").start(); new Thread(()->{ for (int i = 0; i < 10; i++) { data3.printC(); } },"C").start(); } } class Data3{ private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); private int num = 1; // 1A 2B 3C public void printA(){ lock.lock(); try { while (num != 1){ condition1.await(); } System.out.println(Thread.currentThread().getName()+" Im A "); num = 2; //Wake up 2 condition2.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printB(){ lock.lock(); try { while (num != 2){ condition2.await(); } System.out.println(Thread.currentThread().getName()+" Im B "); num = 3; //Wake up 3 condition3.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void printC(){ lock.lock(); try { while (num != 3){ condition3.await(); } System.out.println(Thread.currentThread().getName()+" Im C "); num = 1; // Wake up 1 condition1.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } }