multithreading
Since my internship a few years ago, I have successively written a lot of Markdown notes. Most of my early notes were made by myself and shared with some big bull blogs at B station. The early notes system was relatively clear, which was also my learning and growth route.
The following notes also include some sharing with industry leaders, the official website forum,github to learn a little deeper things and some work experience and stumbles. In the future, I will organize my early notes and my current experiences in study and work into modules and share them irregularly. If you have different opinions, I hope you can express your opinions in the comments section.
I hope we can keep this thinking and love forever.
1. The concept
Threads and processes a Process is a program that is executing, called a Process Thread: A Thread is a path of execution in a Process, and a control unit Thread is a path of execution within a program. Java virtual machines allow applications to run concurrently with multiple execution paths multiprocess: Running multiple programs simultaneously on the operating system multithreading: Java applications are multithreaded applications. One path of execution is the one from the main method, which is called the main thread. The other path is garbage collection (). Worker thread 3. The CPU can only perform one task at A time. Suppose there are three tasks: A, B, and C. The CPU's instantaneous switching is not A random time slice. Each thread is allocated a period of time called slice 4. When to use multithreading? If there are time-consuming tasks during the operation, you can put time-consuming tasks in another thread, such as data request [time-consuming operation] pull up load new data [new data request] --> The thread can not affect other operations, such as looking at other goodsCopy the code
2. How to create a thread
The JDK also provides a thread-to-thread class for threads
Remember: The Java classes that represent threads are either Thread or a subclass of Thread
Thread creation methods: 1. Inherit Thread class 2. Implement Runnable interface
1. Create threads by inheriting the Thread class
1.Declare A class A inherited from Thread and override the run method2.If the Thread wants to be executed, it must be started first. Start run method: the method body stores the tasks of the execution path. Specific steps: step1: create A class and inherit Thread class step2: Step3: start the thread object -- start() the start() method is to notify the CPU that a thread is ready to execute. When is it executed, depending oncpu
start(a)The class FirstThread extends Thread () method opens a Thread so that it can execute 2. The run () method extends Thread{
@Override
public void run(a) {
for(int i = 0; i<1000; i++){ System.out.println("*"); }}}class SecondThread extends Thread{
@Override
public void run(a) {
for(int i = 0; i<1000; i++){ System.out.println("\t\t"+ i); }}}public class Demo03_Thread {
public static void main(String[] args) {
FirstThread firstThread = new FirstThread();
SecondThread secondThread = new SecondThread();
firstThread.start();// Two threads
secondThread.start();// Three threads
// The main thread is finished, but the child thread may not be finished
// A thread can only execute once, which is equivalent to a lifetime}}Copy the code
2. Implement Runnable interface
1.Declare A class A that implements the Runnable interface and override the run method class A in the interface to act as the thread task holder2.Create Thread object bind class A3.Call the start method to start the thread. Step1: define a class that implements the Runnable interface step2: rewrite the run() method, Thread body step3: start the Thread, by implementing the class object, create a Thread class object, in the call Thread class object start() Thread Thread =newThread(objects that implement the Runnable interface); thread.start(); Example:class MyRunnable implements Runnable{
@Override
public void run(a) {
for(int i = 0; i<1000; i++){ System.out.println("\t"+ i); }}}public class Demo04_Runnable {
public static void main(String[] args) {
// Start the thread
MyRunnable myRunnable = new MyRunnable();
// The Thread must be started by calling the start() method, which does not exist in the Runnable object and only exists in the Thread class.
// The Thread constructor only needs to pass a Runnable
// Object to the Thread class
Thread thread = newThread(myRunnable); thread.start(); }}Copy the code
3. Compare the differences between the two creation methods
Comparison of two creation methods: the second method is more flexible than the first method, and the second method is recommended. Java class inheritance mechanism: single inheritance of the first class from the Thread class can not be inherited from other classes to implement other interfaces1.Threads created using the Thread class have multiple copies of their member variables because they create multiple Thread objects2.The thread object mRunnable2, created through the Runnable interface, starts multiple threads that share data pairs of member variables in the object1Description:class MyThread3 extends Thread{
int i = 0;// Member variables, in class, outside the method, belong to the object, create the object only one copy
@Override
public void run(a) {
/ / thread
while (i<10) { System.out.println(i++); }}}public class Demo05_Thread {
public static void main(String[] args) {
MyThread3 t1 = new MyThread3();
MyThread3 t2 = new MyThread3();
MyThread3 t3 = newMyThread3(); t1.start(); t2.start(); t3.start(); }} the result is: 0123456789012345678901234567892Description:class MyRunnable2 implements Runnable{
int i = 0;// Member variables
@Override
public void run(a) {
while (i<10) { System.out.print(i++); }}}public class Demo06_Runnable {
public static void main(String[] args) {
MyRunnable2 mRunnable2 = new MyRunnable2();
Thread t1 = new Thread(mRunnable2);
Thread t2 = new Thread(mRunnable2);
Thread t3 = newThread(mRunnable2); t1.start(); t2.start(); t3.start(); }} The result is 0123456789Copy the code
3. Common thread methods
1, the name of the thread and the current thread get
CurrentThread () : String thread.currentThread (). GetName () : String thread.currentThread ().longThread.currentthread ().getid () : The first way to create a Thread thread.setName (String) The second way to create a Thread is through a constructor, which is in the parent classpublic Thread(String name)The third way to create threads is through constructorspublic Thread(Runnable runnable, String name)
Copy the code
2. Thread sleep
A static methodstatic void sleep(long mills)In the current thread, if the sleep method is called, the current thread enters the sleep state, giving up CPU execution and entering the thread blocking state. When does blocking end?? ----> It is time to sleep. The thread stops blocking and enters the wait state waiting for the CPU to allocate the time sliceCopy the code
3. Thread merge
Object methodsvoid join(a)
void join(long mills)Call thread B's join method in thread A, make thread A give up the execution right of CPU, execute thread B by CPU. At this point in time for thread A thread A is blocked(Give up execution of CPU)Wait until the task on thread B completes(or end of merge time)When will thread A unblock? 1. The task of thread B is finished. 2public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run(a) {
for(int i = 0; i < 1000; i++){
System.out.println(Thread.currentThread().getName() + "~"+ i); }}}; Thread thread =new Thread(runnable, "patter");
thread.start();
for(int i = 1000; i < 2000; i++){
System.out.println("main"+ "~" + i);
if (i == 1010) {
try {
thread.join(5000);
} catch(InterruptedException e) { e.printStackTrace(); }}}}Copy the code
Thread comity
A static methodstatic void yield(a)Suspends the currently executing thread object and cedes execution to another thread of the same or higher prioritypublic static void main(String[] args) {
Runnable target =new Runnable() {
public void run(a) {
for(int i = 0; i < 1000; i++){
System.out.println(Thread.currentThread().getName() + "~"+ i); }}}; Thread thread =new Thread(target, "Thread one");
thread.start();
for(int i = 0; i < 1000; i++){
System.out.println("main" + "~" + i);
if(i == 100){ Thread.yield(); }}}Copy the code
5. Thread priority
The priority of the main thread defaults to5Method of setting the priority of a threadvoid setPriority(int priority)Priority Ranges from 1 to 10 A larger value indicates a higher priority. The priority of a thread is obtainedint getPriority(a)Note: A thread with A higher priority has A greater chance of getting CPU execution than A thread with A lower priority. The priority of Thread B is the same as that of Thread A. The Thread class provides three Thread priority fields MAX_PRIORITY 10 NORM_PRIORITY 5 MIN_PRIORITY 1Copy the code
6. Thread interruption
Object methodsvoid interrupt(a)Call interrupt on thread A to interrupt thread B's blocking state and put thread B into the ready state to wait for the CPU to allocate the time sliceCopy the code
Background thread [Sprite thread/daemon thread]
Garbage collection thread ---- Most classic background thread what background threads do: Serve foreground threads to set a foreground thread as background threadvoid setDaemon(true)Note: 1. The current thread after death, background threads it will die The foreground thread after dying Background didn't immediately the demise of the reason: the current thread JVM will inform the background thread die after death To the background threads to receive and respond to there is a time interval between In this time interval Background threads execute again for a long time 2. The setting statement must be set before the thread starts otherwise an exception will erupt 3. Creating a thread in a foreground thread defaults to a foreground threadCopy the code
4. The five states of threads
New State -- Ready state -- Running State -- Blocked state -- Dead State Created: new() Ready: start() Run: Executed blocked: temporarily abandoned execution, such as sleep() ---- unblocked and entered the ready state Dead: execution finishedCopy the code
5. Synchronize threads
Multiple threads accessing common data can make that data unsafe. This is called inter-thread data security problem (critical resource problem).
Synchronization: allows a certain part of the code to be executed by only one thread at a time and cannot be inserted by other threads
1. Synchronized keyword
1) Synchronize code blocks
Format:synchronized(object){contains data shared by threads}synchronizedThe synchronization keyword is a built-in Java keyword that provides mutually exclusive access to resources at the VM level. Encapsulate the code that needs to be synchronized in a synchronized code block, The object in the synchronized code block is equivalent to adding a lock and monitor on the basis of the synchronized code block When does a thread acquire synchronization locks and supervisors? Automatically release the lock and monitor when the synchronized code block is finished executing. When thread A obtains the synchronization lock and monitor, the other threads must wait outside. For the other threads, this situation indicates that the thread is blocked. When to unblock? After thread A releases the synchronization monitor and lock, the other threads unblock and enter the ready state, waiting for the CPU to allocate the time slice. Note:synchronizedThe latter object can indeed be any object, but ensure that the object is unique to multiple threads === => only one lockCopy the code
2) Synchronization function
If the contents of a method need to be synchronized, you can set the method to be synchronized by adding the synchronization keyword in front of the method. After the method is synchronized, the synchronization lock and the monitor are currently shared objects:thisAfter a static method is synchronized, the synchronization lock and monitor are class objects and only one thread at a time can execute the methodpublic synchronized void add(int x){
// The synchronized code} Synchronization principle: The object to be synchronized: can be any object, requirements: must be all threads can access the object is to use the object mutually exclusive note:1In multithreading, there are security problems of shared data2Synchronized object: multiple threads access the same object A, static B, externally created an object, passed in thread C, string constant D, class. Advantages: Can solve the problem of data security between threads disadvantages:1.It reduces the efficiency of execution,2.Deadlocks are likely to occur.1.Expand the range of locks,2.Try to avoid member variablesCopy the code
3) Example: ticketing problem
1. Implement the synchronization method of the Runnable interface
class MyRunnable1 implements Runnable{
private int tickes = 100;
private boolean flag = true;// Indicate whether tickets can continue to be sold
@Override
public void run(a) {
while(flag) { sale(); }}/ / tickets
public synchronized void sale(a){
if (tickes>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + tickes--);
}else {
flag = false; }}}public class Demo01_Tickes {
public static void main(String[] args) {
MyRunnable1 runnable1 = new MyRunnable1();
Thread t1 = new Thread(runnable1, "Box 1");
Thread t2 = new Thread(runnable1, "Box 2");
Thread t3 = new Thread(runnable1, "Box 3");
Thread t4 = new Thread(runnable1, "Box 4"); t1.start(); t2.start(); t3.start(); t4.start(); }}Copy the code
- A block of synchronized code that inherits the Thread class
class MyThread2 extends Thread{
private static int tickes = 100;
// It must be the same obj
private Object obj ;
//private static Object object = new Object();
public MyThread2(String name,Object obj){
super(name);
this.obj = obj;
}
@Override
public void run(a) {
while (true) {
synchronized (MyThread2.class) {
// This can't lock new many times,
if (tickes>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + tickes--);
}else{
break;
}
}
}
}
}
public class Demo02_Tickes {
public static void main(String[] args) {
Object obj = new Object();
MyThread2 t1 = new MyThread2("Box 1",obj);
MyThread2 t2 = new MyThread2("Box 2",obj);
MyThread2 t3 = new MyThread2("Box 3",obj);
MyThread2 t4 = new MyThread2("Box 4",obj); t1.start(); t2.start(); t3.start(); t4.start(); }}Copy the code
- Inherits the synchronization methods of Thread
class MyThread3 extends Thread{
private static int tickes = 100;
private static boolean flag = true;// Indicate whether tickets can continue to be sold
@Override
public void run(a) {
while(flag) { sale(); }}public static synchronized void sale(a){
if (tickes>0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + tickes--);
}else {
flag = false; }}}public class Demo03_Tickes {
public static void main(String[] args) {
new MyThread3().start();
new MyThread3().start();
new MyThread3().start();
newMyThread3().start(); }}Copy the code
2, the Lock Lock
Lock Lock the Lock and the monitor are different objects. The Lock interface separated from the monitor uses ReentrantLock ReentrantLock Lock =newReentrantLock() Monitor object Condition con = lock.newcondition (); How do I wake up and wait ???? con.await(); Waiting for the con. Signal (); Wake up a con.signalAll(); All ways to use wakeup wait:class X{
// Lock the object
private final ReentrantLock lock = new ReentrantLock();
// The monitor bound to the lock
Condition con = lock.newCondition();
// The method to modify the resource
void method(a){
lock.lock();
try{
// The code to synchronize
}finally{
/ / unlocklock.unlock(); Advantages and disadvantages of multithreading Advantages: Make full use of CPU resources, improve the efficiency of code execution disadvantages: Too many threads reduce the efficiency of code execution. When multiple threads access the same resource and modify the data of the resource, critical resource problems may occur. 0
Copy the code
1) Example: Access problem
class Account{
private double balance = 10000;
/ / lock object
private final ReentrantLock lock = new ReentrantLock();
// Monitor object
Condition condition = lock.newCondition();
/ / add
synchronized void save(double money){
//synchronized (this) {
balance = balance + money;
System.out.println("Current balance is:" + balance);
/ /}
}
/ / make a withdrawal
void get(double money){
/ / lock
lock.lock();
try{
balance = balance - money;
System.out.println("Remaining balance after withdrawal:" + balance);
}finally {
/ / unlocklock.unlock(); }}}class Person extends Thread{
Account account;
double money; // The amount of money that the person should deposit/withdraw
Person(){}
Person(String name, Account account, double money){
super(name);
this.account = account;
this.money = money;
}
public void run(a) {
/ / save
//account.save(money);
/ / make a withdrawalaccount.get(money); }}public class ThreadSafe2 {
public static void main(String[] args) {
Account account = new Account();
Person person = new Person("The road", account, 1000);
Person person2 = new Person("The female emperor",account, 5000);
person.start();
person2.start();
Person person3 = new Person("Her beauty", account, 1000);
Person person4 = new Person("Sauron", account, 8000); person3.start(); person4.start(); }}Copy the code
2) Example: deadlock
Break down the deadlock: blog.csdn.net/hd12370/art…
class MyRunnable5 implements Runnable{
private static String milk = "Milk";
private static String bread = "Bread";
boolean flag = true;//1
@Override
public void run(a) {
/ / t1 zhang SAN
if (flag) {
synchronized (milk) {// Lock the milk
System.out.println(Thread.currentThread().getName() +
"\t already owned"+milk+", also want:"+ bread);
synchronized (bread) {// Lock the bread
System.out.println(Thread.currentThread().getName() +
"\t is in possession"+milk+", have again:"+ bread); }}}/ / t2 li si
else {
synchronized (bread) {
System.out.println(Thread.currentThread().getName() +
"\t already owned"+bread+", also want:"+ milk);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (milk) {
System.out.println(Thread.currentThread().getName() +
"\t is in possession"+bread+", have again:"+ milk);
}
}
}
}
}
public class Demo05_DeadLock {
public static void main(String[] args) {
MyRunnable5 mt1 = new MyRunnable5();
mt1.flag = true;
Thread t1 = new Thread(mt1,"Zhang");
MyRunnable5 mt2 = new MyRunnable5();
mt2.flag = false;
Thread t2 = new Thread(mt2,"Bill"); t1.start(); t2.start(); }}Copy the code
6. Thread wake up and wait
1. Wait and wake up methods
Methods that use threads to wait and wake up (methods in Object) to wait are requiredvoid wait(a)Caller: Synchronize monitor objects This method is associated withsynchronizedCombined use: Method of waking up the current thread by putting it into sleepvoid notify(a)Wake up a thread that has been put to sleep by waiting.void notifyAll(a)Wake up all thread callers that have been put to sleep by the WAIT method: synchronization monitor object --> Need to be the same as the object that called the wait methodsynchronizedNote: Wake up before waiting. Avoid waiting for an unwakeable situation.wait(a) -- > Object
sleep(a)-- > Thread wake up:wait(a)-- > To be awakened:notify(a) notifyAll(a)
sleep(a)-- > Wake up when it's timeCopy the code
2. Classic case: producer-consumer issues
Steamed bun:
public class ManTou {
private int id;
public ManTou(a) {
super(a); }public ManTou(int id) {
super(a);this.id = id;
}
public int getId(a) {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString(a) {
return "ManTou [id=" + id + "]"; }}Copy the code
Basket:
public class Basket {
private ManTou[] manTous = new ManTou[5];
private int index = 0;
public synchronized void addManTou(ManTou manTou) throws InterruptedException {
if (index == manTous.length){
System.out.println("Basket full, producers wait.");
wait();
}else{
manTous[index] = manTou;
index++;
System.out.println("The producer produced a steamed bread:" + manTou + "The basket already contains:" + index + "A steamed bun.");
}
Thread.sleep(100);
notify();// Wake up, if there is no wait () thread, is an empty wake, equivalent to a blank wake
//notifyAll(); // There are multiple producers, so use this method to wake up all waiting threads
}
public synchronized ManTou getManTou(a) throws InterruptedException {
ManTou manTou;
if (index == 0){
manTou = null;
System.out.println("Basket empty, consumers wait.");
wait();
}else{
index--;
manTou = manTous[index];
System.out.println("The consumer consumed a steamed bun:" + manTou + "Also in the basket:" + index + "A steamed bun.");
}
Thread.sleep(100);
notify();
returnmanTou; }}Copy the code
Producers and consumers:
/ / producer
class Producer implements Runnable{
private Basket basket;
private int id = 1;// The number of buns produced by the user starts from 1 by default
public Producer(Basket basket){
this.basket = basket;
}
@Override
public void run(a) {
while (true) {
// Produce steamed bread and add the produced steamed bread to the basket
ManTou manTou = newManTou(id++); basket.add(manTou); }}}/ / consumer
class Customer implements Runnable{
private Basket basket;
public Customer(Basket basket){
this.basket = basket;
}
@Override
public void run(a) {
while (true) { basket.get(); }}}// Production and consumption process
public class ProAndCus {
public static void main(String[] args) {
Basket basket = new Basket();
Producer producer = new Producer(basket);
Customer customer = new Customer(basket);
Thread t1 = new Thread(producer, "Chef");
Thread t2 = new Thread(customer, "Version"); t1.start(); t2.start(); }}Copy the code
7. The thread pool
class Task implements Runnable{
@Override
public void run(a) {
for(int i = 0; i<10; i++){ System.out.println(Thread.currentThread().getName() +"\t"+ i); }}}public class Demo_ThreadPool {
public static void main(String[] args) {
// If you want to use a thread pool: the thread does not need to create itself, the thread pool creates it for us
// create a thread pool object
/ / newSingleThreadExecutor only one thread in the pool,
//ExecutorService es = Executors.newSingleThreadExecutor();
// Specifies the number of threads -- common
// If 5 tasks are required, perform 3 tasks first and then 2 more
//ExecutorService es = Executors.newFixedThreadPool(3);
// Thread pool with cache, depending on system performance, create thread
//ExecutorService es = Executors.newCachedThreadPool();
Task t1 = new Task();
Task t2 = new Task();
Task t3 = new Task();
Task t4 = new Task();
Task t5 = new Task();
// es.execute(t1);
// es.execute(t2);
// es.execute(t3);
// es.execute(t4);
// es.execute(t5);
// Delay execution
ScheduledExecutorService es = Executors.newScheduledThreadPool(1);
es.schedule(t1, 10, TimeUnit.SECONDS); }}Copy the code