Thread pool BlockingQueue synchronized volatile

I read an article about " a 3 Years of experience as a programmer should have the skills " article , Take a beating . A lot of familiar and unfamiliar knowledge makes me doubt that I am a fake programmer . This chapter starts with thread pool , Blocking queues ,synchronized and volatile keyword ,wait,notify Method to realize the communication between threads , Deadlock , I often take the interview questions . Integrate these pieces of knowledge together . As shown in the figure below .

Learning flow chart :



technology :Executors,BlockingQueue,synchronized,volatile,wait,notify

explain : Article learning ideas : Thread pool ----> queue ----> keyword ----> Deadlock ----> Thread pool practice

Source code :https://github.com/ITDragonBlog/daydayup/tree/master/ThreadBase

Thread pool

Thread pool , As the name suggests, the pool where threads are stored , It's analogous to the connection pool of a database . Because the frequent creation and destruction of threads will bring a lot of pressure to the server . If you can save the created thread in the pool for the next task instead of destroying it , You can not only reduce the time it takes to create and destroy threads , Improved performance , It also reduces the pressure on the server .

The use of thread pools

There are five core parameters to initialize the thread pool , Namely corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue. There are also two default parameters threadFactory, handler

corePoolSize: Initial number of core threads in thread pool . When initializing the thread pool , There are no threads in the pool , Threads are created only when the task is executed .

maximumPoolSize: The maximum number of threads allowed in the thread pool . If it exceeds that number , Default prompt RejectedExecutionException abnormal

keepAliveTime: When the current number of threads is greater than the core thread , This parameter takes effect , The purpose is to terminate the maximum time that redundant idle threads wait for new tasks . That is, the thread that has not received the task will be destroyed within the specified time .

unit:keepAliveTime Time unit of

workQueue: The queue for caching tasks , It is generally used LinkedBlockingQueue.

threadFactory: The factory used by the executor to create a new thread , Generally, the default value .

handler: The handler used when execution is blocked due to exceeding thread scope and queue capacity , Generally, the default value .

Thread pool workflow

Start , There's a student in the swimming pool , So the librarian arranged a coach to train the student ;

then , There are six students in the swimming pool , But the owner only recruited five coaches , So one student was arranged to wait in the lounge ;

later , Sixteen students came to the swimming pool , The lounge is full , The owner of the museum checked the expenses , It is expected to recruit up to ten coaches ;

Last , Only ten students came to the swimming pool , The manager said to the coach , If you can't get the coach in half a day, you can go ;

result , There are no students in the swimming pool , Shut down the .

Before taking over the mission , There are no threads in the thread pool . Only when the task comes will the new thread be created . When the number of tasks is greater than the number of core threads , The task enters the queue and waits . If the queue is full , The thread pool adds new threads until the maximum number of threads . More than that, the rejection policy will be executed .

Three kinds of shutdown of thread pool

shutdown: The thread pool no longer receives tasks , Wait for all tasks in the thread pool to complete , Close thread pool . Commonly used

shutdownNow: The thread pool no longer receives tasks , Ignore tasks in the queue , Try to interrupt a task in progress , Return to the list of unimplemented tasks , Close thread pool . Use with caution

awaitTermination: The thread pool can continue to receive tasks , When the task is done , Or beyond the set time , Close thread pool . Method is blocked , Consider using

The type of thread pool

1 newSingleThreadExecutor() Single-threaded thread pool

Both the initial number of threads and the maximum number of threads allowed are one ,keepAliveTime It's not working , Queues are unbounded blocking queues . The main function of the thread pool is to be responsible for caching tasks .

2 newFixedThreadPool(n) Fixed size thread pool

The initial number of threads is the same as the maximum number of threads allowed , And the size is custom ,keepAliveTime It's not working , Queues are unbounded blocking queues . Meet most business requirements , Commonly used .

3 newCachedThreadPool() Cache unbounded thread pool

The initial number of threads is zero , The maximum number of threads is infinite ,keepAliveTime 60 The second class terminates the idle thread , Queues are unbuffered and unbounded . It's suitable for scenes with few tasks , Use with caution .

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; /**
* Thread pool
* advantage , Analogy to database connection pool
* 1. Frequent creation and destruction of threads will bring great pressure to the server
* 2. If the created thread is not destroyed, it is left in the thread pool waiting for the next use , It will greatly improve the efficiency and reduce the pressure on the server
*
* Three workQueue Strategy
* Submit directly SynchronousQueue
* Unbounded queue LinkedBlockingQueue
* Bounded queues ArrayBlockingQueue
*
* Four rejection strategies
* AbortPolicy : JDK Default , beyond MAXIMUM_POOL_SIZE Give up the mission and throw an exception RejectedExecutionException
* CallerRunsPolicy : Attempt to call the rejected task directly , If the line pool is closed , Then discard the task
* DiscardOldestPolicy : Abandon the first task in the queue , Then try again to perform the rejected task . If the line pool is closed , Then discard the task
* DiscardPolicy : Give up tasks that cannot be performed without throwing exceptions
*/
public class ThreadPoolExecutorStu { // The initial number of threads in the thread pool
private final static Integer CORE_POOL_SIZE = 3;
// The maximum number of threads allowed in the thread pool
private final static Integer MAXIMUM_POOL_SIZE = 8;
// When the number of threads is larger than the initial thread . The maximum time to terminate redundant idle threads waiting for new tasks
private final static Long KEEP_ALIVE_TIME = 10L;
// Task cache queue , That is, when the number of threads is greater than the initial number of threads, first enter the queue to wait , This number can be set a little bit larger , Avoid errors when the number of threads exceeds the maximum number of threads . Or just use unbounded queues
private final static ArrayBlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<Runnable>(5); public static void main(String[] args) {
Long start = System.currentTimeMillis();
/**
* ITDragonThreadPoolExecutor Time consuming 1503
* ITDragonFixedThreadPool Time consuming 505
* ITDragonSingleThreadExecutor Grammar error report ,
* ITDragonCachedThreadPool Time consuming 506
* Custom thread pool is recommended , or newFixedThreadPool(n)
*/
ThreadPoolExecutor threadPoolExecutor = ITDragonThreadPoolExecutor();
for (int i = 0; i < 8; i++) { // perform 8 A mission , If more than MAXIMUM_POOL_SIZE May be an error RejectedExecutionException
MyRunnableTest myRunnable = new MyRunnableTest(i);
threadPoolExecutor.execute(myRunnable);
System.out.println(" The current number of threads in the thread pool is :"+threadPoolExecutor.getPoolSize()+", The number of tasks waiting to be executed in the queue is :"+
threadPoolExecutor.getQueue().size());
}
// Turn off the thread pool , It doesn't stop immediately ( Stop receiving external submit Mission , Wait for internal tasks to complete before stopping ), Recommended . The corresponding is shutdownNow, It is not recommended to use
threadPoolExecutor.shutdown();
try {
// Block waiting 30 Turn off the pool in seconds , return true It means it has been closed . and shutdown Different , It can receive external tasks , And it's blocking . Here for the convenience of counting time , So choose block wait to close .
threadPoolExecutor.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(" Time consuming : " + (System.currentTimeMillis() - start));
} // Custom thread pool , Development recommends using
public static ThreadPoolExecutor ITDragonThreadPoolExecutor() {
// Construct a , The initial number of threads is 3, The maximum thread data is 8, Waiting time 10 minute , The queue length is 5 Thread pool of
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.MINUTES, WORK_QUEUE);
return threadPoolExecutor;
} /**
* Fixed size thread pool
* corePoolSize The initial number of threads and maximumPoolSize The maximum number of threads is the same ,keepAliveTime Parameters don't work ,workQueue Using unbounded blocking queues
*/
public static ThreadPoolExecutor ITDragonFixedThreadPool() {
ExecutorService executor = Executors.newFixedThreadPool(8);
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
return threadPoolExecutor;
} /**
* Single-threaded thread pool
* Equivalence and Executors.newFixedThreadPool(1);
*/
public static ThreadPoolExecutor ITDragonSingleThreadExecutor() {
ExecutorService executor = Executors.newSingleThreadExecutor();
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
return threadPoolExecutor;
} /**
* Unbounded thread pool
* corePoolSize The initial number of threads is zero
* maximumPoolSize The maximum number of threads is infinite
* keepAliveTime 60 The second class will terminate the unused thread
* workQueue SynchronousQueue queue , No capacity , New threads will be added directly to the task
* It is not recommended to use
*/
public static ThreadPoolExecutor ITDragonCachedThreadPool() {
ExecutorService executor = Executors.newCachedThreadPool();
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
return threadPoolExecutor;
} } class MyRunnableTest implements Runnable {
private Integer num; // Number of tasks in progress
public MyRunnableTest(Integer num) {
this.num = num;
}
public void run() {
System.out.println(" Ongoing MyRunnable " + num);
try {
Thread.sleep(500);// Simulating the execution of a transaction takes time
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("MyRunnable " + num + " completion of enforcement ");
}
}

queue

queue , It's a data structure . Most of the queues are based on FIFO( fifo ) Sort the elements in the same way (PriorityBlockingQueue It's sorted by priority ). The head of the queue removes the element , Insert an element at the end of the queue . The inserted element proposal cannot be null.Queue There are two main categories , One is high performance queue ConcurrentLinkedQueue; One is blocking queues BlockingQueue. This chapter focuses on BlockingQueue

ConcurrentLinkedQueue

ConcurrentLinkedQueue Better performance than BlockingQueue. Is an unbounded thread safe queue based on linked nodes . The elements of the queue follow the first in, first out principle . Don't allow null Elements .

BlockingQueue

ArrayBlockingQueue: Array based blocking queue , A fixed length array is maintained internally , To cache data objects in the queue . There is no separation of read and write , That means production and consumption can't go hand in hand . It's a bounded queue

LinkedBlockingQueue: List based blocking queues , A data buffer queue is maintained internally ( It consists of a linked list ), The implementation adopts separate lock ( Read write separation of two locks ), In order to realize the complete parallel operation of producer and consumer operation . It's an infinite line , You can also specify the queue size

SynchronousQueue: No cached queues , The data produced by survivors will be directly obtained and consumed by consumers . If you call the stack method directly without data, an error will be reported .

Three queue usage scenarios

newFixedThreadPool The queue used by thread pool is LinkedBlockingQueue. Its advantage is unbounded cache , Internal implementation of read-write separation , Concurrent processing power is higher than ArrayBlockingQueue

newCachedThreadPool The queue used by thread pool is SynchronousQueue. The advantage is that there is no cache , All tasks received can be processed directly , Again , Use with caution !

The amount of concurrency is small , Server performance is good , Consider using SynchronousQueue.

The amount of concurrency is large , Server performance is good , Consider using LinkedBlockingQueue.

There's a lot of concurrency , Server performance cannot meet , Consider using ArrayBlockingQueue. The stability of the system is the most important .

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import org.junit.Test; /**
* Blocking queues
* ArrayBlockingQueue : bounded
* LinkedBlockingQueue : unbounded
* SynchronousQueue : No buffer. Use it directly
* Non blocking queues
* ConcurrentLinkedQueue : High performance
*/
public class ITDragonQueue { /**
* ArrayBlockingQueue : Implementation of blocking queue based on array , A fixed length array is maintained internally , To cache data objects in the queue .
* There is no internal separation of read and write , Production and consumption cannot go hand in hand ,
* Length needs to be defined ,
* You can specify FIFO or FIFO ,
* It's a bounded queue .
*/
@Test
public void ITDragonArrayBlockingQueue() throws Exception {
ArrayBlockingQueue<String> array = new ArrayBlockingQueue<String>(5); // You can try The queue length is determined by 3 Change to 5
array.offer("offer Insert data method --- Successfully returns true Otherwise return to false");
array.offer("offer 3 Insert data method in seconds ", 3, TimeUnit.SECONDS);
array.put("put Insert data method --- But beyond the length of the queue, it blocks waiting , no return value ");
array.add("add Insert data method --- But if the queue length exceeds, it will prompt java.lang.IllegalStateException"); // java.lang.IllegalStateException: Queue full
System.out.println(array);
System.out.println(array.take() + " \t There are elements left : " + array); // Take the element out of the head , And delete it from the queue , If the queue is null Then wait all the time
System.out.println(array.poll() + " \t There are elements left : " + array); // Take the element out of the head , And delete it from the queue , perform poll after One less element
System.out.println(array.peek() + " \t There are elements left : " + array); // Take the element out of the head , perform peek Don't remove elements
} /**
* LinkedBlockingQueue: List based blocking queues , A data buffer queue is maintained internally ( The queue consists of a linked list ).
* Its internal implementation uses read-write separation lock , It can process concurrent data efficiently , Completely parallel operation of producer and consumer operations
* No length can be specified ,
* It's an infinite line .
*/
@Test
public void ITDragonLinkedBlockingQueue() throws Exception {
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
queue.offer("1. Unbounded queue ");
queue.add("2. Grammar and ArrayBlockingQueue almost ");
queue.put("3. Realize the separation of reading and writing ");
List<String> list = new ArrayList<String>();
System.out.println(" Returns the length of the intercept : " + queue.drainTo(list, 2));
System.out.println("list : " + list);
} /**
* SynchronousQueue: Queues without buffers , The data produced by survivors will be directly obtained and consumed by consumers .
*/
@Test
public void ITDragonSynchronousQueue() throws Exception {
final SynchronousQueue<String> queue = new SynchronousQueue<String>();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("take , Blocking is handled until a value is taken : " + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
Thread.sleep(2000);
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
queue.add(" Advance value !!!");
}
});
thread2.start();
} /**
* ConcurrentLinkedQueue: It is a queue suitable for high concurrency scenarios , Through the unlocked way , High performance in high concurrency state is realized , Better performance than BlockingQueue.
* It's an unbounded thread safe queue based on linked nodes . The elements of the queue follow the first in, first out principle . The head was the first to join , The tail is the last to be added , Don't allow null Elements .
* No blocking queues , No, put and take Method
*/
@Test
public void ITDragonConcurrentLinkedQueue() throws Exception {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();
queue.offer("1. High performance, non blocking ");
queue.add("2. Unbounded queue ");
System.out.println(queue);
System.out.println(queue.poll() + " \t : " + queue); // Take the element out of the head , And delete it from the queue , perform poll after One less element
System.out.println(queue.peek() + " \t : " + queue); // Take the element out of the head , perform peek Don't remove elements
} }

keyword

Keyword is for thread safety service , What is thread safety ? When multiple threads access a class ( Object or method ) when , This object always shows the right behavior , So this class ( Object or method ) It's thread safe .

Two features of thread safety : Atomicity and visibility .synchronized Sync , Atomicity .volatile visibility .wait,notify Responsible for communication between multiple threads .

synchronized

synchronized You can lock any object or method , And the code that locks is called " Mutual exclusion zone " or " A critical region ", If a thread wants to execute synchronized Decorated code block , First of all

step1 Trying to get a lock

step2 If I get the lock , perform synchronized Code body content

step3 If you can't get the lock , The thread will keep trying to get the lock , Until we get it , And multiple threads are competing for the lock at the same time .

notes *( There are too many threads, that is, there will be lock competition , Multiple threads execute in the order of CPU According to the order of distribution , Not the sequence of code execution )

synchronized Can modify methods , Decorated code block , These are object locks . If and static Use it together , Upgrade to class lock .

synchronized Locks can be reentered , When a thread gets a lock on an object , When you request the object again, you can get the lock of the object again . Lock reentry mechanism , It also supports the scenario of parent-child class inheritance .

synchronized Synchronous asynchronous , After a thread gets a lock on an object , Other threads can perform non locking methods ( asynchronous ). But you can't perform other locking methods ( Sync ).

synchronized Abnormal lock , When an exception occurs in the code executed by a thread , The lock it holds will be released automatically .

/**
* synchronized keyword , Can modify methods , You can also modify code blocks . The latter is recommended , By reducing the granularity of locks , To improve system performance .
* synchronized keyword , If you use a string as a lock , Please note that String The cache function of constant pool and whether the lock is true after the string is changed .
* synchronized Lock reentry , When a thread gets a lock on an object , When you request the object again, you can get the lock of the object again .
* synchronized Homoasynchrony , After a thread gets a lock , Another thread can perform non synchronized The method of decoration , It's asynchronous . If another thread performs any synchronized The method of modification needs to wait , This is synchronization
* synchronized Kind of lock , use static + synchronized Modifier means to lock the whole class
*/
public class ITDragonSynchronized { private void thisLock () { // Object lock
synchronized (this) {
System.out.println("this Object lock !");
}
} private void classLock () { // Kind of lock
synchronized (ITDragonSynchronized.class) {
System.out.println("class Kind of lock !");
}
} private Object lock = new Object();
private void objectLock () { // Any object lock
synchronized (lock) {
System.out.println("object Any object lock !");
}
} private void stringLock () { // String lock , Be careful String The cache function of constant pool
synchronized ("string") { // use new String("string") t4 and t5 Enter at the same time . use string t4 After completion ,t5 At the beginning
try {
for(int i = 0; i < 3; i++) {
System.out.println("thread : " + Thread.currentThread().getName() + " stringLock !");
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} private String strLock = "lock"; // String lock change
private void changeStrLock () {
synchronized (strLock) {
try {
System.out.println("thread : " + Thread.currentThread().getName() + " changeLock start !");
strLock = "changeLock";
Thread.sleep(500);
System.out.println("thread : " + Thread.currentThread().getName() + " changeLock end !");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} private synchronized void method1() { // Lock reentry
System.out.println("^^^^^^^^^^^^^^^^^^^^ method1");
method2();
}
private synchronized void method2() {
System.out.println("-------------------- method2");
method3();
}
private synchronized void method3() {
System.out.println("******************** method3");
} private synchronized void syncMethod() {
try {
System.out.println(Thread.currentThread().getName() + " synchronized method!");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} // If this method also adds synchronized, You have to wait t1 After thread execution ,t2 To call , Two synchronized Blocks are mutually exclusive ,synchronized Block gets an object lock , It's the whole object that's locked
private void asyncMethod() {
System.out.println(Thread.currentThread().getName() + " asynchronized method!");
} // static + synchronized Modifier means class lock , The result of printing is thread1 Finish the line first , And then in the thread2 Threads . If not static modification , be thread1 and thread2 Almost simultaneously , End at the same time
private synchronized void classLock(String args) {
System.out.println(args + "start......");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(args + "end......");
} public static void main(String[] args) throws Exception {
final ITDragonSynchronized itDragonSynchronized = new ITDragonSynchronized();
System.out.println("------------------------- synchronized Code block lock -------------------------");
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.thisLock();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.classLock();
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.objectLock();
}
});
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(2000);
System.out.println("------------------------- synchronized String locking -------------------------");
// If the string lock , use new String("string") t4,t5 Threads can acquire locks , If used directly "string" , If the lock does not release ,t5 The thread is processing and waiting
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.stringLock();
}
}, "t4");
Thread thread5 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.stringLock();
}
}, "t5");
thread4.start();
thread5.start(); Thread.sleep(3000);
System.out.println("------------------------- synchronized String variable lock -------------------------");
// The string has changed , The lock will also change , Lead to t7 The thread is in t6 When the thread is not finished, it begins to execute , But the properties of an object change , Does not affect the lock of this object .
Thread thread6 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.changeStrLock();
}
}, "t6");
Thread thread7 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.changeStrLock();
}
}, "t7");
thread6.start();
thread7.start(); Thread.sleep(2000);
System.out.println("------------------------- synchronized Lock reentry -------------------------");
Thread thread8 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.method1();
}
}, "t8");
thread8.start();
Thread thread9 = new Thread(new Runnable() {
@Override
public void run() {
SunClass sunClass = new SunClass();
sunClass.sunMethod();
}
}, "t9");
thread9.start(); Thread.sleep(2000);
System.out.println("------------------------- synchronized Synchronous asynchronous -------------------------");
Thread thread10 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.syncMethod();
}
}, "t10");
Thread thread11 = new Thread(new Runnable() {
@Override
public void run() {
itDragonSynchronized.asyncMethod();
}
}, "t11");
thread10.start();
thread11.start(); Thread.sleep(2000);
System.out.println("------------------------- synchronized Synchronous asynchronous -------------------------");
ITDragonSynchronized classLock1 = new ITDragonSynchronized();
ITDragonSynchronized classLock2 = new ITDragonSynchronized();
Thread thread12 = new Thread(new Runnable() {
@Override
public void run() {
classLock1.classLock("classLock1");
}
});
thread12.start();
Thread thread13 = new Thread(new Runnable() {
@Override
public void run() {
classLock2.classLock("classLock2");
}
});
thread13.start();
} // A class with parent-child inheritance , If it's all used synchronized keyword , It's also thread safe .
static class FatherClass {
public synchronized void fatherMethod(){
System.out.println("#################### fatherMethod");
}
} static class SunClass extends FatherClass{
public synchronized void sunMethod() {
System.out.println("@@@@@@@@@@@@@@@@@@@@ sunMethod");
this.fatherMethod();
}
}
}

volatile

volatile Although the keyword does not have synchronized The atomicity of keywords ( Sync ) But its main function is to make variables visible in multiple threads . That's visibility .

It's easy to use , Directly used to modify variables . Because it's not atomic , It can be used Atomic Class substitution . What's missing in the ointment is many Atomic Classes don't have atomicity either , So we need to synchronized To modify .

volatile How keywords work

Each thread has its own working memory , If a thread needs to use a variable , Will copy a copy from the main memory to their own working memory . So it improves efficiency . After each thread execution, synchronize variables from working memory back to main memory .

So there's a problem , Variables may have different values in different threads . If you use volatile Keyword modifier variable , Will let the thread's execution engine get the value directly from main memory .

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; /**
* volatile Keyword is mainly used to make variables visible in multiple threads .
* volatile Keywords are not atomic , but Atomic Classes are atomic and visible .
* What's missing in the ointment is many Atomic Class is not atomic , Still need synchronized Keywords help .
*/
public class ITDragonVolatile{ private volatile boolean flag = true;
private static volatile int count;
private static AtomicInteger atomicCount = new AtomicInteger(0); // Add static This is to avoid the initial value of zero every time an object is instantiated // test volatile Keyword visibility
private void volatileMethod() {
System.out.println("thread start !");
while (flag) { // If flag by true It's always blocked ,
}
System.out.println("thread end !");
} // verification volatile Keywords are not atomic
private int volatileCountMethod() {
for (int i = 0; i < 10; i++) {
// The first thread has not yet count Add to 10 When , It may be modified by another thread . May cause the last printed value not to be 1000
count++ ;
}
return count;
} // verification Atomic Class is atomic
private int atomicCountMethod() {
for (int i = 0; i < 10; i++) {
atomicCount.incrementAndGet();
}
// If last printed as 1000 Is atomic , The information printed in the middle may be affected by println Delay effects .
return atomicCount.get();// If last printed as 1000 Is atomic
} // Verify multiple Atomic Class operations are not atomic , Add synchronized Keyword modification can be
private synchronized int multiAtomicMethod(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicCount.addAndGet(1);
atomicCount.addAndGet(2);
atomicCount.addAndGet(3);
atomicCount.addAndGet(4);
return atomicCount.get(); // If atomic , Then all the returned results must be 10 Multiple , It takes several runs to see the results
} /**
* volatile Keyword visibility reasons
* There are two threads : One is main The main thread , One is thread The child thread of
* jdk Thread workflow : In order to improve efficiency , Each thread has a working memory , Copy the main memory variables to the working memory . The thread's execution engine gets variables directly from working memory .
* So The problem is coming. :thread Threads use their own working memory , The main thread modifies the variable ,thread Threads don't know . That's the problem with invisible data .
* resolvent : Variable usage volatile After keyword modification , The thread's execution engine gets variables directly from main memory .
*
*/
public static void main(String[] args) throws InterruptedException {
// test volatile Keyword visibility
/*ITDragonVolatile itDragonVolatile = new ITDragonVolatile();
Thread thread = new Thread(itDragonVolatile);
thread.start();
Thread.sleep(1000); // When the thread starts , Set the value again
itDragonVolatile.setFlag(false);
System.out.println("flag : " + itDragonVolatile.isFlag());*/ // verification volatile Keywords are not atomic and Atomic Class is atomic
final ITDragonVolatile itDragonVolatile = new ITDragonVolatile();
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 100; i++) {
threads.add(new Thread(new Runnable() {
@Override
public void run() {
// The information printed in the middle may be affected by println Delay effects , Look at the last print
System.out.println(itDragonVolatile.multiAtomicMethod());
}
}));
}
for(Thread thread : threads){
thread.start();
}
} public boolean isFlag() {
return flag;
} public void setFlag(boolean flag) {
this.flag = flag;
} }

wait,notify

Use wait/ notify Method to realize the communication between threads , simulation BlockingQueue queue . There are two points to note :

1)wait and notify Must cooperate synchronized Keyword use

2)wait The method is to release the lock , notify Method does not release the lock .

Thread communication concept : Threads are independent individuals in the operating system , But if these individuals don't go through special treatment , Can't be a whole , Communication between threads becomes one of the necessary methods of the whole .

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger; /**
* synchronized You can lock any object or method , And the code that locks is called " Mutual exclusion zone " or " A critical region ", Generally lock the code block , Improve performance by reducing lock granularity .
* Atomic* To make up for volatile The key words are not atomic . Although a Atomic* Objects are atomic , But there is no guarantee that more than one Atomic* Objects are also atomic .
* volatile Keywords don't have synchronized The main function of keyword atomicity is to make variables visible in multiple threads .
* wait / notify
* wait() Make threads block running ,notify() A thread waiting for the same shared resource in the random wake-up waiting queue continues to run ,notifyAll() Wake up all threads in the waiting queue waiting for the same shared resource to continue running .
* 1)wait and notify Must cooperate synchronized Keyword use
* 2)wait The method is to release the lock , notify Method does not release the lock
*/
public class ITDragonMyQueue { //1 You need a collection of loading elements
private LinkedList<Object> list = new LinkedList<Object>();
//2 You need a counter AtomicInteger ( To ensure atomicity and visibility )
private AtomicInteger count = new AtomicInteger(0);
//3 There needs to be upper and lower limits
private final Integer minSize = 0;
private final Integer maxSize ; //4 Construction method
public ITDragonMyQueue(Integer size){
this.maxSize = size;
} //5 Initialize an object For locking
private final Object lock = new Object(); //put(anObject): hold anObject Add to BlockingQueue in , If BlockQueue There's no space , The thread calling this method is blocked , until BlockingQueue There's room to move on .
public void put(Object obj){
synchronized (lock) {
while(count.get() == this.maxSize){
try {
lock.wait(); // When Queue When there is no space , Thread blocked , Here to distinguish , Name it wait1
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(obj); //1 Add elements
count.incrementAndGet(); //2 Counter accumulation
lock.notify(); //3 After adding elements , Notify another thread wait2, One more element in the queue , It's time to remove .
System.out.println(" The newly added element is : " + obj);
}
} //take: Take away BlockingQueue Top of the list , if BlockingQueue It's empty , Block to wait until BlockingQueue New data is added .
public Object take(){
Object ret = null;
synchronized (lock) {
while(count.get() == this.minSize){
try {
lock.wait(); // When Queue When it's not worth it , Thread blocked , Here to distinguish , Name it wait2
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ret = list.removeFirst(); //1 Do the remove element operation
count.decrementAndGet(); //2 Counter decrement
lock.notify(); //3 After removing the element , Wake up another thread wait1, There are fewer elements in the queue , You can add more operations
}
return ret;
} public int getSize(){
return this.count.get();
} public static void main(String[] args) throws Exception{
final ITDragonMyQueue queue = new ITDragonMyQueue(5);
queue.put("a");
queue.put("b");
queue.put("c");
queue.put("d");
queue.put("e");
System.out.println(" The length of the current container : " + queue.getSize());
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
queue.put("f");
queue.put("g");
}
},"thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(" The removed element is :" + queue.take()); // Remove one element and add another , Instead of removing both , Into two elements .
System.out.println(" The removed element is :" + queue.take());
}
},"thread2");
thread1.start();
Thread.sleep(2000);
thread2.start();
}
}

Deadlock

Deadlock is a bad situation , The lock is delayed , Other threads can only wait and block all the time . Like threads A Have a lock , But still want to lock two . Threads B Have lock two , But I still want to lock it . Two threads don't give way to each other , Two threads will wait forever .

screening :

First step : Console input jps Used to get the current JVM Process pid

The second step :jstack pid Used to print stack information

The third step : Reading ,"Thread-1" It's the name of the thread ,prio Is the priority of the thread ,tid Is the thread id, nid It's a local thread id, waiting to lock Waiting to get the lock ,locked The lock you own .

"Thread-1" #11 prio=5 os_prio=0 tid=0x0000000055ff1800 nid=0x1bd4 waiting for monitor entry [0x0000000056e2e000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.itdragon.keyword.ITDragonDeadLock.rightLeft(ITDragonDeadLock.java:37)
- waiting to lock <0x00000000ecfdf9d0> (a java.lang.Object)
- locked <0x00000000ecfdf9e0> (a java.lang.Object)
at com.itdragon.keyword.ITDragonDeadLock$2.run(ITDragonDeadLock.java:54)
at java.lang.Thread.run(Thread.java:748)
/**
* Deadlock : Threads A Have a lock , But still want to lock two . Threads B Have lock two , But I still want to lock it . Two threads don't give way to each other , Two threads will wait forever .
* avoid : In the design stage , Understand the sequence of locks , Reduce the number of lock interactions .
* screening :
* First step : Console input jps Used to get the current JVM Process pid
* The second step :jstack pid Used to print stack information
* "Thread-1" #11 prio=5 os_prio=0 tid=0x0000000055ff1800 nid=0x1bd4 waiting for monitor entry [0x0000000056e2e000]
* - waiting to lock <0x00000000ecfdf9d0> - locked <0x00000000ecfdf9e0>
* "Thread-0" #10 prio=5 os_prio=0 tid=0x0000000055ff0800 nid=0x1b14 waiting for monitor entry [0x0000000056c7f000]
* - waiting to lock <0x00000000ecfdf9e0> - locked <0x00000000ecfdf9d0>
* It can be seen that , The lock held by two threads is the lock that the other thread wants ( Not get forever in the commotion ), And the last line was printed Found 1 deadlock.
*/
public class ITDragonDeadLock { private final Object left = new Object();
private final Object right = new Object(); public void leftRight(){
synchronized (left) {
try {
Thread.sleep(2000); // Simulate the process of holding a lock
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (right) {
System.out.println("leftRight end!");
}
}
} public void rightLeft(){
synchronized (right) {
try {
Thread.sleep(2000); // Simulate the process of holding a lock
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (left) {
System.out.println("rightLeft end!");
}
}
} public static void main(String[] args) {
ITDragonDeadLock itDragonDeadLock = new ITDragonDeadLock();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
itDragonDeadLock.leftRight();
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
itDragonDeadLock.rightLeft();
}
});
thread2.start();
} }

Multithreaded case

If you have any Thread1、Thread2、Thread3、Thread4 Statistics of four threads C、D、E、F Size of four disks , All threads are counted and handed over to Thread5 Thread to do summary , How to realize

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* If you have any Thread1、Thread2、Thread3、Thread4 Statistics of four threads C、D、E、F Size of four disks , All threads are counted and handed over to Thread5 Thread to do summary , How to realize ?
* reflection : Summary , Explain to return the result of four threads to the fifth thread , If the thread has a return value , Recommended callable.Thread and Runnable No return value
*/
public class ITDragonThreads { public static void main(String[] args) throws Exception {
// Unbuffered unbounded thread pool
ExecutorService executor = Executors.newFixedThreadPool(8);
// relative ExecutorService,CompletionService Can be more accurate and simple to complete the execution of asynchronous tasks
CompletionService<Long> completion = new ExecutorCompletionService<Long>(executor);
CountWorker countWorker = null;
for (int i = 0; i < 4; i++) { // Four threads are responsible for the statistics
countWorker = new CountWorker(i+1);
completion.submit(countWorker);
}
// Close thread pool
executor.shutdown();
// The main thread is equivalent to the fifth thread , Used to aggregate data
long total = 0;
for (int i = 0; i < 4; i++) {
total += completion.take().get();
}
System.out.println(total / 1024 / 1024 / 1024 +"G");
}
} class CountWorker implements Callable<Long>{
private Integer type;
public CountWorker() {
}
public CountWorker(Integer type) {
this.type = type;
} @Override
public Long call() throws Exception {
ArrayList<String> paths = new ArrayList<>(Arrays.asList("c:", "d:", "e:", "f:"));
return countDiskSpace(paths.get(type - 1));
} // Count disk size
private Long countDiskSpace (String path) {
File file = new File(path);
long totalSpace = file.getTotalSpace();
System.out.println(path + " Total space size : " + totalSpace / 1024 / 1024 / 1024 + "G");
return totalSpace;
}
}

Look up the face-to-face questions

1 Common ways to create threads and their advantages and disadvantages

(1) Inherit Thread class (2) Realization Runnable Interface

Advantages and disadvantages : Implementing an interface is more flexible than inheriting a class , Reduce the coupling between programs . The drawback is that there's a little more code .

2 start() Methods and run() Differences in methods

start Method to start a thread , and run It's just thread A normal method call of .

3 The role of multithreading

(1) Play multi-core CPU The advantages of , Improve CPU Utilization ratio (2) To prevent blocking , Increase of efficiency

4 What is thread safety

When multiple threads access a class ( Object or method ) when , This object always shows the right behavior , So this class ( Object or method ) It's thread safe .

5 Thread security level

(1) immutable (2) Absolute thread safety (3) Relative thread safety (4) Thread is not safe

6 How to share data between two threads

Data sharing between threads , In fact, it can be understood as the communication between threads , It can be used wait/notify/notifyAll Wait and wake up .

7 The benefits of using thread pools

Avoid creating and destroying threads frequently , Achieve the reuse of Thread objects , Improve performance , Reduce server pressure . Using thread pool can also flexibly control the number of concurrency according to the project .

8 sleep Methods and wait What's the difference

sleep Methods and wait Methods can be used to give up CPU For a certain time ,sleep yes thread Methods , It won't release the lock .wait yes object Methods , Can release the lock .

summary

1 The core parameters of thread pool are Initial number of core threads , The maximum number of threads that the thread pool runs , Idle thread lifetime , Time unit , Task queue .

2 A queue is a data structure , There are two main categories Blocking queues BlockingQueue, And non blocking high performance queues ConcurrentLinkedQueue.

3 Two features of thread safety , Atomicity and visibility .synchronized Keywords are atomic .volatile Keywords have visibility .

4 Single Atomic Classes have atomicity and visibility , Multiple Atomic Class is not atomic , need synchronized Keyword modification .

5 When the lock held by two threads is the lock that the other party wants, it is easy to cause deadlock , Minimize lock interaction by design .

That's the end of the chapter , There are many knowledge points involved , Please refer to the flow chart to learn . If you have any questions, please point out . If you like, you can order " recommend "

Thread pool queue synchronized More articles about

  1. From thread pool to synchronized Keyword details

    Thread pool BlockingQueue synchronized volatile I read an article about " a 3 Years of experience as a programmer should have the skills " article , Take a beating . A lot of familiar and unfamiliar knowledge ...

  2. javaWeb Use thread pool + Queue resolution &quot; Order concurrence &quot; problem

    Solution : Use thread pool + queue Project based on Spring, If not spring You need to put ThreadPoolManager.java Change to singleton mode 1. Write a Controller(Spring mvc) / ...

  3. Java The thread pool queue is too full , I've been holding on ?java The queue is too large to cause memory overflow

    Java Of Executors The fixed length line pool provided by the framework is used internally by default LinkedBlockingQueue As a container for tasks , There is no limit to the size of this queue , It can be infinitely inward submit Mission . When thread pool processing is too slow , ...

  4. java Thread pool synchronized lock

    //Object Defines an object of reference type for locking static Object Lock = new Object(); // Define a int Type variable 0 Do the initial value static int iCheck = ...

  5. Step on the pit Spring Cloud Hystrix Thread pool queue configuration

    background : Once in a production environment , All of a sudden, a lot of repayment orders have been suspended , Later, we investigated the cause , It was found that there was an internal system call Hystrix Call exception . In the development process , Because the number of core threads is relatively large , There is no such anomaly . Put it in the test environment , Once in a while ...

  6. Source analysis ThreadPoolExecutor Thread pool and blocking queue

    This article is right ThreadPoolExecutor Thread pool of the underlying source code analysis , How does thread pool play the role of thread reuse . How to maintain our thread task ? Let's get straight to the point : First let's take a look ThreadPoolExecuto ...

  7. Java Principle and implementation of thread pool

    I'm learning thread pool recently . Memory control and other programming techniques to improve program performance , I saw a friend on the Internet who wrote well , So share with you . Suggest : Before reading this article , Let's start with the synchronous knowledge , especially syncronized Synchronous keyword usage . Turn off ...

  8. Java Principle and implementation of thread pool ( turn )

    These days is mainly crazy to see the source program , While making up for some previous knowledge gaps , Also learned a lot of new knowledge ( such as NIO), Or new technology . Thread pool is one of them , When it comes to threads , We'll think of the past < operating system > The producers and consumers of the market , ...

  9. establish Java Thread pool

    Role of thread pool : The role of thread pool is to limit the number of execution threads in the system . According to the environment of the system , You can set the number of threads automatically or manually , Achieve the best effect of operation : Less waste of system resources , Too much congestion results in low efficiency of the system . Use thread pool to control the number of threads , Other lines ...

Random recommendation

  1. Winform Picture mouse scroll view ( Zoom in , narrow , rotate , Drag to see )[ Daily essay ]

    Method ten million , I'm just one of them [ By controlling PictureBox To control the picture , The image is fully displayed in the control ]... I haven't done it for a long time , It's a little strange ! Add mouse scrolling to form construction : /// <summary> /// forms ...

  2. 09Mybatis_ Entry procedure —— Delete users and update users

    Delete user : Or the previous case , Nothing else , Just two changes .1.user.xml Files and 2.Mybatis_first.java file user.xml The file code is modified as follows : <?xml version ...

  3. InstallShield Limited Edition for Visual Studio 2013

    InstallShield Limited Edition for Visual Studio 2013 Text course ( Teach you how to pack .NET Framework go in ) In this paper, from “ Wule bar Software Station ”, Link to the original text :h ...

  4. nginx Source code installation

    Installation environment : operating system :Ubuntu 12.04 Nginx:     V1.4.2 PCRE:    V8.33 zlib:         V1.2.8 Download the above source package to the current user's home directory ( This machine :/hom ...

  5. MapReduce elementary analysis

    I used it a long time ago Hadoop, But yes MapReduce The specific data flow process in is not very clear , use Python Streamming I wrote a few MapReduce, I have a certain understanding of this process . First we know that ,Ma ...

  6. LeetCode And “ mathematics ”:Plus One

    Topic link Subject requirements : Given a non-negative number represented as an array of digits, plus one to the number. Th ...

  7. python Learning the second 6 God

    id is ==  Code block Caching mechanism of code block Small data pools ( Caching mechanisms for different code blocks ) Small data pools ( Resident mechanism ) summary Conversion between data types int bool str The transformation of the three is possible . bool Can work with all data classes ...

  8. APIView technological process —— Request mode distribution

  9. How to view a class Is the document correct

    There's a problem today , It's just that you can't find the problem , Try multiple paths to solve the problem , The mistake remains . Then I got the bag at the scene , There's a big problem that I've overlooked , This class File cannot be opened with decompiler (jd-gui.exe), It's amazing , but ...

  10. Photoshop Mixed mode of

    1. Brightness is the relative brightness of a color , Saturation is the purity of a color ( How much gray is in the color ) 2. Mixed mode The color pixels of the lower image are called " Basic colors ": The selected one is called " blend " Color , For the most part ...