[](
)Callable thread creation
public class CallableTest { public static void main(String[] args) throws ExecutionException,InterruptedException { // new Thread(new Runnable()).start(); // new Thread(new FutureTask<V>()).start(); // new Thread(new FutureTask<V>( Callable )).start(); new Thread().start(); // How do I start Callable MyThread thread = new MyThread(); FutureTask futureTask = new FutureTask(thread); // Adaptation class new Thread(futureTask,"A").start(); new Thread(futureTask,"B").start(); // The results are cached and efficient Integer o = (Integer) futureTask.get(); //This get method may cause blocking! Put him in last // Or use asynchronous communication to process! System.out.println(o); } } class MyThread implements Callable<Integer> { @Override public Integer call() { System.out.println("call()"); // Several call s will be printed // Time consuming operation return 1024; } }
[](
)Thread pool
The top-level interface of thread pool in Java is Executor, but strictly speaking, Executor is not a thread pool, but just a tool for executing threads. The real thread pool interface is ExecutorService.
Thread pool: three methods, seven parameters and four rejection strategies
[](
)Benefits of thread pooling
-
Reduce resource consumption
-
Improve response speed
-
Easy to manage.
[](
)Three methods
-
Executors. Newsinglethreadexecution() creates a thread to execute
-
Executors.newFixedThreadPool(Int i) creates I threads to execute
-
Executors.newCachedThreadPool() cache pool, scalable, strong in case of strength and weak in case of weakness
Create code:
public static void main(String[] args) { ExecutorService threadPool = Executors.newSingleThreadExecutor();// Single thread //ExecutorService threadPool = Executors.newFixedThreadPool(5); // Create a fixed thread pool size //ExecutorService threadPool = Executors.newCachedThreadPool(); // Scalable, strong in case of strength, weak in case of weakness try { for (int i = 0; i < 100; i++) { // After using thread pool, use thread pool to create threads threadPool.execute(()->{ System.out.println(Thread.currentThread().getName()+" ok"); }); } } catch (Exception e) { e.printStackTrace(); } finally { // When the thread pool runs out, the program ends. Close the thread pool threadPool.shutdown(); } }
Seven parameters
Source code analysis of three methods:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } //All three methods return the ThreadPoolExecutor() class
Source code analysis of ThreadPoolExecutor (seven parameters):
public ThreadPoolExecutor( int corePoolSize, // Core thread pool size int maximumPoolSize, // Maximum core thread pool size long keepAliveTime, // If no one calls it, it will be released TimeUnit unit, // Timeout unit BlockingQueue<Runnable> workQueue, // Blocking queue ThreadFactory threadFactory, // Thread factory: it is used to create threads. Generally, it does not need to be moved RejectedExecutionHandler handle // Reject Policy){ if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ?null:AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
Four rejection strategies
image-20210527134117484 /** * new ThreadPoolExecutor.AbortPolicy() //When the bank is full, someone else comes in. If you don't deal with this person, throw an exception * new ThreadPoolExecutor.CallerRunsPolicy() //Where to go! * new ThreadPoolExecutor.DiscardPolicy() //If the queue is full, lose the task and no exception will be thrown! * new ThreadPoolExecutor.DiscardOldestPolicy() //When the queue is full, try to compete with the earliest, and no exception will be thrown *
[](
)Thread lifecycle (state)
When a thread is created and started, it neither enters the execution state as soon as it is started, nor is it always in the execution state
public enum State { // At this time, only the JVM allocates memory for it and initializes the value of its member variable NEW, // After calling the start() method, the thread is running, and the Java virtual opportunity creates a method call stack and a program counter for it, waiting for the scheduled run RUNNABLE, // block BLOCKED, // Wait, wait, wait WAITING, // Timeout wait TIMED_WAITING, // termination TERMINATED; }
[](
)Thread termination method
In addition to normal exit, there are three ways to end a thread
-
Set the exit flag to make the thread exit normally, that is, when the run() method is completed, the thread terminates
-
Interrupt the thread using the interrupt() method
-
Use the stop method to forcibly terminate the thread (not recommended)
1. Use the exit flag to terminate the thread
The most direct way is to set a boolean flag and control whether the while loop exits by setting this flag to true or false
public class ThreadSafe extends Thread { public volatile boolean exit = false; public void run() { while (!exit){ //do something } } }
2. Interrupt the current thread with the interrupt() method
There are two ways to interrupt a thread using the interrupt() method:
-
The thread is in a blocking state. When calling the thread's interrupt() method, an interrupt exception will be thrown. The method in the block throws the exception, catches the exception through the code, and then break s out of the loop state, giving us a chance to end the execution of the thread.
-
If the thread is not in the blocking state, use isInterrupted() to judge the interrupt flag of the thread to exit the loop.
Code demonstration:
//First case public class ThreadSafe extends Thread { public void run() { while (true){ try{ Thread.sleep(5*1000);//Blocking 5 wonderful }catch(InterruptedException e){ e.printStackTrace(); break;//After the exception is caught, execute break to jump out of the loop. } } } } //The second case public class ThreadSafe extends Thread { public void run() { while (!isInterrupted()){ //do something, but no throw InterruptedException } } }
3. Use the stop method to terminate the thread
Thread can be used directly in the program Stop () to forcibly terminate the thread, but the stop method is very dangerous
Unsafe mainly include:
thread. After the stop () call, the thread creating the child thread will throw the ThreadDeath error error and release all locks held by the child thread. Generally, any lock code block is used to protect the consistency of data, if thread. Is called If all locks held by this thread are released suddenly (uncontrollable) after stop (), the protected data may be inconsistent, and other threads may cause some strange application errors when using these corrupted data.
[](
)Java thread lock
[](
)Optimistic lock
Optimistic locking is an optimistic idea, that is, it thinks that there are more reads and fewer writes, and the possibility of concurrent writes is low. Every time you get the data, you think others will not modify it, so you won't lock it. However, when updating, you will judge whether others have updated the data during this period, and take the operation of reading the current version number first and then locking it, If it fails, repeat the read compare write operation.
Optimistic locks in java are basically implemented through CAS operation, which is an updated atomic operation
[](
)Pessimistic lock
Pessimistic locking is a pessimistic idea, that is, it is considered that there are many writes and there is a high possibility of concurrent writes. Every time you go to get the data, you think others will modify it, so you will lock it every time you read and write the data, so that others will block the data until they get the lock.
The pessimistic lock in java is Synchronized
[](
)Spin lock
If the thread holding the lock can release the lock resources in a very short time, those threads waiting for the competing lock do not need to switch between the kernel state and the user state to enter the blocking pending state. They only need to wait (spin) and obtain the lock immediately after the thread holding the lock releases the lock, so as to avoid the consumption of switching between the user thread and the kernel
[](
)Advantages and disadvantages
Spin lock_ Minimize thread blocking,
This can greatly improve the performance of code blocks that do not have fierce lock competition and occupy a very short lock time, because the consumption of spin will be less than that of thread blocking, suspending and waking up operations, which will lead to two context switches of threads!
However, if the lock competition is fierce, or the thread holding the lock needs to occupy the lock for a long time to execute the synchronization block, it is not suitable to use the spin lock, because the spin lock always occupies the cpu for useless work before obtaining the lock, accounting for XX or XX. At the same time, a large number of threads compete for a lock, which will lead to a long time to obtain the lock, The consumption of thread spin is greater than that of thread blocking and pending operation, and other threads that need a cup cannot obtain the cpu, resulting in a waste of cpu. So in this case, we have to turn off the spin lock;
[](
)Synchronized synchronization lock
synchronized, which can treat any non NULL object as a lock. It is an exclusive pessimistic lock and a reentrant lock.
[](
)Synchronized scope
-
When acting on a method, it locks the instance of the object (this);
-
When it is used for static methods, the Class instance is locked. This static method lock is equivalent to a global lock of the Class and will lock all threads calling the method
-
When synchronized acts on an object instance, it locks all code blocks that lock the object.
[](
)Lock lock
//Lock lock usually uses reentrant lock ReentrantLock Lock lock = new ReentrantLock();
ReentantLock inherits the interface Lock and implements the methods defined in the interface. It is a reentrant Lock. In addition to completing all the work that synchronized can do, it also provides methods to avoid multi-threaded deadlock, such as responding to interrupt Lock, polling Lock request, timing Lock, etc
public class SaleTicketDemo02 { public static void main(String[] args) { // Concurrency: multiple threads operate on the same resource class and throw the resource class into the thread Ticket2 ticket = new Ticket2(); // @Functional interface, jdk1 8 lambda expression (parameter) - > {code} new Thread(()->{for (int i = 1; i < 40 ; i++) ticket.sale();},"A").start(); new Thread(()->{for (int i = 1; i < 40 ; i++) ticket.sale();},"B").start(); new Thread(()->{for (int i = 1; i < 40 ; i++) ticket.sale();},"C").start(); } } // Lock Trilogy // 1, new ReentrantLock(); // 2, lock.lock(); // Lock // 3, finally=> lock. unlock(); // Unlock class Ticket2 { // Properties and methods private int number = 30; Lock lock = new ReentrantLock(); public void sale(){ lock.lock(); // Lock try { // Business code if (number>0){ System.out.println(Thread.currentThread().getName()+"Sold"+ (number--)+"ticket,surplus:"+number); } } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); // Unlock } } }
[](
)The difference between synchronized and lock locks
-
synchronized is a built-in keyword in java, and lock is a java class
-
synchronized cannot obtain the lock status. Lock can determine whether the lock has been obtained
-
synchronized will automatically release the lock. Lock will not automatically release the lock. You need to release the lock manually. If you don't release the lock, it will cause deadlock
-
synchronized thread 1 (obtains the lock, and then the lock is blocked) and thread 2 (waits, and then waits foolishly), the lock lock does not necessarily wait
-
synchronized reentrant lock, which cannot be interrupted. It is not fair. Lock reentrant lock, which can judge whether the lock is fair or not, can be set by itself
-
synchronized is suitable for a small number of code synchronization problems, and lock is suitable for a large number of code synchronization problems
[](
)Fair lock and unfair lock
Fair lock: very fair: you can come first
Unfair lock: very unfair: you can jump the queue (default)
[](
)Read write lock
In order to improve performance, Java provides read-write locks. Read locks are used where you read and write locks are used where you write. It can be controlled flexibly,
If there is no write lock, the read is non blocking, which improves the execution efficiency of the program to a certain extent.
Read / write locks are divided into read locks and write locks. Multiple read locks are not mutually exclusive. Read locks and write locks are mutually exclusive. This is controlled by the jvm itself. You only need to install the corresponding locks.
Read lock
If your code is read-only data and many people can read it at the same time, but can't write it at the same time, put on the read lock
Write lock
If your code modifies data and only one person is writing and cannot read it at the same time, then write the lock. In short, read the lock when reading, write the lock when writing!
// Locked class MyCacheLock{ private volatile Map<String,Object> map = new HashMap<>(); // Read / write locks: more granular control private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private Lock lock = new ReentrantLock(); // When saving and writing, you only want one thread to write at the same time public void put(String key,Object value){ readWriteLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName()+"write in"+key); map.put(key,value); System.out.println(Thread.currentThread().getName()+"write in OK"); } catch (Exception e) { e.printStackTrace(); } finally { readWriteLock.writeLock().unlock(); } } // Take, read, everyone can read! public void get(String key){ readWriteLock.readLock().lock(); try { System.out.println(Thread.currentThread().getName()+"read"+key); Object o = map.get(key); System.out.println(Thread.currentThread().getName()+"read OK"); } catch (Exception e) { e.printStackTrace(); } finally { readWriteLock.readLock().unlock(); } } }
[](
)Lock optimization
Reduce lock holding time
Only lock programs with thread safety requirements
Reduce lock granularity
Split a large object (which may be accessed by many threads) into small objects, which greatly increases the degree of parallelism and reduces lock competition.
Lock separation
The most common lock separation is ReadWriteLock, which is divided into read lock and write lock according to the function. In this way, reading is not mutually exclusive, reading and writing are mutually exclusive, which not only ensures thread safety, but also improves performance,
Lock coarsening
Each thread is required to hold the lock as short as possible, that is, the lock should be released immediately after using the public resources.
However, everything has a degree. If the same lock is constantly requested, synchronized and released, it will consume valuable resources of the system, which is not conducive to performance optimization
Lock elimination
If you find objects that cannot be shared, you can eliminate the lock operation of these objects
deadlock
A deadlock occurs when two or more threads are waiting for each other to complete execution before proceeding. The result is that these threads are trapped in infinite waiting.
How to avoid thread deadlock?
Just break one of the four conditions that cause deadlock.
-
Destroy mutually exclusive condition: we can't destroy this condition, because we use locks to make them mutually exclusive (critical resources need mutually exclusive access).
-
Destruction request and retention conditions: apply for all resources at one time.
-
Destroy the condition of no deprivation: when a thread occupying some resources further applies for other resources, if it fails to apply, it can actively release the resources it occupies.
-
Breaking the cycle waiting condition: prevent by applying for resources in order. Apply for resources in a certain order, and release resources in reverse order
[](
)Thread basic method
Thread related basic methods include wait, notify, notifyAll, sleep, join, yield, etc.
[](
)Thread wait
The thread calling this method enters the WAITING state. It will return only after WAITING for the notification of another thread or being interrupted. It should be noted that after calling the wait() method, the lock of the object will be released.
[](
)Thread sleep
Sleep causes the current thread to sleep. Unlike the wait method, sleep does not release the lock currently held. sleep(long) causes the thread to enter the timed-waiting state, while the wait() method causes the current thread to enter the waiting state
[](
)Thread yield
yield will cause the current thread to give up the CPU execution time slice and compete for the CPU time slice again with other threads. In general, threads with high priority are more likely to successfully compete for CPU time slices
[](
)Thread interrupt
Interrupting a thread is intended to give the thread a notification signal, which will affect an interrupt identification bit inside the thread. The thread itself does not change state
[](
)Join waits for other threads to terminate
When a thread's join() method is invoked in the current thread, the current thread becomes blocked until the end of another thread, and the current thread is changed from blocking state to ready state, waiting for cpu's favor.
last
Java architecture advanced interview and knowledge point document notes
This document has 498 pages in total, including interview analysis and knowledge points sorting of Java collection, concurrent programming, JVM, Dubbo,Redis, Spring, MySQL, Kafka, etc
Java distributed advanced interview question parsing document
All of them include distributed interview question analysis, including distributed message queue, Redis cache, sub database and sub table, micro service architecture, distributed high availability, read-write separation, etc!
Analysis of necessary questions and document learning notes for Internet Java programmer interview
Java architecture advanced video analysis collection
Unlike the wait method, sleep does not release the lock currently held. sleep(long) will cause the thread to enter the timed-waiting state, while the wait() method will cause the current thread to enter the waiting state
[](
)Thread yield
yield will cause the current thread to give up the CPU execution time slice and compete for the CPU time slice again with other threads. In general, threads with high priority are more likely to successfully compete for CPU time slices
[](
)Thread interrupt
Interrupting a thread is intended to give the thread a notification signal, which will affect an interrupt identification bit inside the thread. The thread itself does not change state
[](
)Join waits for other threads to terminate
When a thread's join() method is invoked in the current thread, the current thread becomes blocked until the end of another thread, and the current thread is changed from blocking state to ready state, waiting for cpu's favor.
last
Java architecture advanced interview and knowledge point document notes
This document has 498 pages in total, including interview analysis and knowledge points sorting of Java collection, concurrent programming, JVM, Dubbo,Redis, Spring, MySQL, Kafka, etc
[external chain picture transferring... (img-QSD92rv9-1630719958408)]
Java distributed advanced interview question parsing document
All of them include distributed interview question analysis, including distributed message queue, Redis cache, sub database and sub table, micro service architecture, distributed high availability, read-write separation, etc!
[external chain picture transferring... (img-hiMT9yjC-1630719958409)]
Analysis of necessary questions and document learning notes for Internet Java programmer interview
[external chain picture transferring... (img-aLDZF00x-1630719958411)]
Java architecture advanced video analysis collection