Learning resources are organized from: Station B "Crazy God Talk"
Java multithreading basics
Knowledge point segmentation:
- Multithreading overview
- Thread realization: inherit Thread, realize Runnable, realize Callable, Lamdb expression
- Concurrency
- Some operations of threads
- Thread lock
- Advanced topics
1. Overview of multithreading
Process
A process can have multiple threads.
Thread
- Thread is independent execution path
- When the program is running, there is no thread created by itself, and there will be multiple threads in the background, such as the main thread and gc thread.
- main() is called the main thread, the entrance of the system, used to execute the entire program
- In a process, if multiple threads are opened, the running of the threads will be arranged and scheduled by the scheduler. The scheduler is related to the operating system Jinmi, and the order cannot be interfered by human intervention.
- When operating on the same resource, there will be resource grabbing problems, and concurrency control needs to be added
- Threads will bring additional overhead such as cpu scheduling time, concurrency control
- Each thread interacts in its own working memory. Improper memory control will cause data inconsistency
2. Implementation of threads
Inherit Thread
The custom class inherits Thread and overrides the run() method. Threads are not necessarily executed immediately and are scheduled by the CPU.
Call: instantiate a custom class, execute run() or start();
- The run method will return to the main thread after execution;
- The start method is executed "simultaneously" with the main thread
Disadvantages: limitations of single inheritance
Implement Runnable (emphasis)
Create a thread class, implement the Runnable interface, and implement the run method. Create Thread, pass this thread class as a parameter, and start it.
Call: instantiate the thread class, then create a Thread object, pass the thread class into the Thread constructor, and execute the start method of the Thread object.
Simulate ticket grabbing system, multi-threaded manipulation of the same resource
/**
* 抢车票
* @author: stone
* @create: 2020-08-13 15:14
*/
public class TestRunnable01 implements Runnable {
//车票总数
private int ticketTotal = 50;
@Override
public void run() {
while (true) {
if (ticketTotal <= 0) {
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "抢到第" + ticketTotal-- + "票");
}
}
public static void main(String args[]){
TestRunnable01 ticket = new TestRunnable01();
new Thread(ticket,"小石").start();
new Thread(ticket,"周杰伦").start();
new Thread(ticket,"黄牛").start();
}
}
#结果
周杰伦抢到第50票
黄牛抢到第49票
小石抢到第49票
黄牛抢到第47票
周杰伦抢到第48票
小石抢到第46票
周杰伦抢到第45票
......
Implement Callable (understand)
- To implement the Callable interface, the return value type is required
- Rewrite call method, need to throw an exception
- Create a target audience
- Create an execution service: ExecutorService ser=Executors.newFixedThreadPool(1);
- Submit for execution: Funture result1=ser.submit(t1);
- Get the execution result: boolean r1 = result1.get();
- Shut down the service: ser.shutdownNow();
Advantages: contain return value, can throw exception;
Lamda expression
Concept: simplify the code, remove temporary variables, and make the core part of the code more prominent.
Functional interface: An interface containing only one abstract method is called a functional interface.
Evolution process:
- Custom class implements functional interface
- Write internal classes to implement functional interfaces
- Static inner class implements functional interface
- Anonymous inner class, instantiate the interface directly and implement abstract methods
- lambda expression, write method body
Thread thread = new Thread(()->{
System.out.println("线程体");
});
3. Static proxy
Agency model concept:
- It is true that the object and the proxy object must have an interface in advance
- Proxy objects
- advantage:
- Proxy objects can do many things that real objects cannot do
- Really the subject is focused on doing his own thing
//真实类实现Runnable接口
class TrulyObj implement Runnable(){}
//线程类实现了Runnable接口 (代理)
class Thread implement Runnable(){}
//使用代理类去执行真实类
new Thread(trulyObj).start();
//start也是执行了run方法,而run方法在真实类中重写了
4. Thread operation
Thread life cycle:
Common API:
/**
* 测试stop
* 1、推荐使用flag标示,让线程自行停止,不建议死循环
* 2、推荐使用次数控制
* 3、不推荐使用stop()和destroy()
* @author: stone
* @create: 2020-08-13 16:48
*/
public class TestStop implements Runnable {
private boolean flag = true;
public void setFlag(boolean f) {
if(this.flag){
System.out.println("子线程停止======");
}
this.flag = f;
}
@Override
public void run() {
while (flag) {
System.out.println("子线程在跑----------------");
}
}
public static void main(String args[]) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 30; i++) {
if (i >= 10) {
testStop.setFlag(false);
}
System.out.println("主线程在跑:" + i);
}
}
}
-
Thread sleep
Thread.sleep(time);
- Sleep the current thread for the specified number of milliseconds
- There is an exception InterruptedException
- The program enters the ready state after the sleep time is reached
- Sleep can simulate test network delay, countdown, etc. (increasing the probability of event occurrence)
- Every object has a lock, sleep will not cast a lock
-
Thread Polite
Thread.yield();
- Polite thread, let the currently executing thread pause, but not block
- Turn the thread from the running state to the ready state and make it go to the queue to get the CPU
- Politeness just allows the CPU to reschedule, not necessarily suspending the current thread to execute other threads
-
Thread jump
thread.join();
- After the execution of this thread is completed, other threads are executed, and other threads are blocked
-
Thread state
Thread.State enum
thread.getState();
- NEW thread is not started
- RUNNABLE thread runs in JVM
- BLOCKED is blocked waiting
- WAITING waiting for another thread to perform a specific action
- TIMED WAITNG thread waits for the specified time
- TERMINATED is over
-
Thread priority
-
Java provides a thread scheduler to monitor all threads that enter the ready state after startup in the program. The thread scheduler decides which thread to schedule first to execute according to the priority.
-
The priority of the thread is expressed in numbers, ranging from 1 to 10
- Thread.MIN_PRIORITY = 1;
- Thread.MAX_PRIORITY = 10;
- Thread.NORM_PRIORITY = 5;
-
Get priority: thread.getPriority();
-
Set priority: thread.setPriority(int x);
-
The priority of the main method is 5;
-
Set the priority first, then start;
-
High priority does not necessarily start early
-
-
Daemon
- Threads are divided into user threads and daemon threads
- The virtual machine must ensure that the user thread finishes execution
- The virtual machine does not need to wait for the daemon thread to finish executing
- Examples: background recording operation log thread, monitoring memory thread, garbage collection waiting thread
thread.setDaemon(true);//Set as a daemon thread
5. Thread synchronization
Concurrency: multiple threads operate the same object at the same time
Queue and lock synchronized
Queuing, when a thread obtains an exclusive lock on an object and monopolizes resources, other threads must wait for the user to release the lock before proceeding
-
A thread holding a lock will cause other threads to hang;
-
Under multi-thread competition, locking and releasing locks will cause more context switching and scheduling delays, causing performance problems
-
If a high-priority thread is waiting for a low-priority thread to release the lock, it will cause priority inversion and cause performance problems
-
Synchronized block: syschronized(Obj ){}
-
Obj calls it a sync monitor
- Obj can be any object, but it is recommended to use shared resources as a synchronization monitor
- There is no need to specify a synchronization monitor in the synchronization method, because the synchronization monitor of the synchronization method is this class of the current object itself
-
Synchronization monitor execution process
- The first thread accesses, obtains the lock of the synchronization monitor, and executes the code
- Access by the second thread, waiting for the first thread to release the lock of the synchronization monitor, unable to access
- After the first thread is executed, the lock of the synchronization monitor is released
- The second thread accesses, obtains the lock of the synchronization monitor, and executes the code
6. Deadlock
Multiple threads each occupy some shared resources, and wait for the resources occupied by other threads to execute each other, causing two or more threads to wait.
The cause of deadlock:
- Mutually exclusive conditions: a resource can only be executed by one process at a time (lock)
- Request and hold conditions: when a process is blocked by requesting resources, keep the acquired resources
- Non-deprivation conditions: the resources already acquired by the process cannot be deprived before they are used up
- Circulation waiting condition: a kind of cyclic waiting resource relationship is formed between several processes.
7. Lock (lock)
- Starting from JDK5.0, Java provides a more powerful thread synchronization mechanism-to achieve synchronization by explicitly defining synchronization lock objects. Synchronization locks use the Lock object as
- The java.util.concurrent.locks.Lock interface is a tool for controlling multiple threads to access shared resources. The lock provides exclusive access to shared resources. Only one thread can lock the Lock object at a time, and the thread starts to access the shared resource. The Lock object should be obtained before the resource
- The ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized. In the realization of thread-safe control, ReentrantLock is commonly used, which can display locks and release locks.
//定义lock锁
private final ReentrantLock look = new ReentrantLock();
try{
lock.lock();//加锁
......
}finnally{
lock.unlock();//解锁
}
Comparison of synchronized and Lock
synchronized | Lock |
---|---|
Implicit lock, automatically cast out of scope | Display lock, manually open and close |
JVM will spend less time to schedule threads, better performance | |
Better scalability, providing more sub-categories |
8. Thread communication
wait();//Hang up and wait until other threads notify, wait will release the lock
wait(long timeout);//Specify the number of milliseconds to wait
notify();//Wake up a thread in a waiting state
notifyAll();//Wake up all threads calling the wait() method on the same object, and the higher priority is scheduled first
PS: All methods of the Object class can only be used in synchronous methods or synchronous code blocks, otherwise an exception IllegalMonitorStateException will be thrown
Concurrent collaboration model: "producer/consumer model"
Producer-> Product -> Consumer
Management method
-
Producer: The module responsible for producing data (methods, objects, threads, processes)
-
Consumer: the module responsible for processing data (methods, objects, threads, processes)
-
Buffer: Consumers cannot directly use the producer’s data, and a "buffer" is established in the middle
The producer puts the product into the buffer, and the consumer takes the product from the buffer
Producer --> Buffer --> Consumer
Semaphore method
By operating a mark together as a switch, communication between threads is realized.
The producer completes the production, opens the label, and informs the consumer to use the product.
After the consumer finishes using the product, the label is turned off and the producer is notified to produce the product.
flag
9, thread pool
Create multiple threads, put them in the thread pool, get them directly when used, and put them back into the thread pool after use
advantage:
- Reduce resource consumption and improve response speed (reduce thread creation time and machine resources)
- Facilitate thread management
- corePoolSize: the size of the core pool
- maximumPoolSize: Maximum number of threads
- keepAliveTime: the most often alive time when the thread has no task
Use thread pool:
- JDK5.0 provides thread pool API: ExecutorService and Executors
- ExecutorService: The real thread pool interface. Common subclass ThreadPoolExecutor
- void execute(Runnable command): execute task/command without return value, generally used to execute Runnable
- Future submit (Callable task): execute task, return value, generally used to execute Callable
- void shutdown(): close the connection pool
- Executors: Tool classes, thread pool tool classes, used to create and return different types of thread pools .
ExecutorService executorService = Executors.newFixedThreadPool(10);