1. Process? Thread? Multitasking?
In fact, there are a lot of cool programs in each process, such as cool browser, cool video, and so on. The thread is a branch or phenomenon in the process, which is an independent execution path. A process includes at least one thread. Threads can be understood as improving the efficiency of program operation, or performing their respective duties. For example, QQ can not only type and chat at the same time, but also voice. For example, when there are three lanes on the highway, vehicles can run at the same time, making full use of the road, which greatly improves the traffic efficiency.
2. How threads are created
Common Thread creation methods include Thread, Runnable, Callable and Thread pool.
Official description of Thread:
2.1 steps of thread creation:
.Custom thread class inheritance Thread .rewrite run()Method to write the thread execution program body .Create a thread object and call start()Method to start the thread.
2.1.1 MyThreadt test
package com.thread; public class MyThread extends Thread { @Override public void run() { for (int i = 0; i <30 ; i++) { System.out.println("Child thread running:"+i); } } }
package com.test; import com.thread.MyThread; public class CommonTest { public static void main(String[] args) { //Custom thread MyThread myThread = new MyThread(); myThread.start(); //main thread for (int i = 0; i < 500; i++) { System.out.println("Main thread running:" + i); } } }
2.1.2 multi thread downloading pictures
1. Import jar
2. Create download class
3. Custom thread class
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
package com.test; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; /** * Custom download class */ public class WebDownload { //Download method public void downloadFile(String url, String fileName) { try { FileUtils.copyURLToFile(new URL(url), new File(fileName)); } catch (IOException e) { e.printStackTrace(); System.out.println("File download failed"); } } }
package com.thread; import com.test.WebDownload; //Multi thread synchronous downloading of pictures public class DownloadThread extends Thread { //Network picture address private String url; //file name private String name; public DownloadThread(String url, String name) { this.url = url; this.name = name; } @Override public void run() { WebDownload webDownload = new WebDownload(); webDownload.downloadFile(url, name); System.out.println("Downloaded file, file name:" + name); } public static void main(String[] args) { DownloadThread downloadThread=new DownloadThread("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F24%2F20190124212555_aAzHh.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1620823150&t=52bd044f2ba560bfe9ca51bb1b07221e","zhangjianing"); DownloadThread downloadThread2=new DownloadThread("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F24%2F20190124212555_aAzHh.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1620823150&t=52bd044f2ba560bfe9ca51bb1b07221e","zhangjianing2"); DownloadThread downloadThread3=new DownloadThread("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F24%2F20190124212555_aAzHh.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1620823150&t=52bd044f2ba560bfe9ca51bb1b07221e","zhangjianing3"); downloadThread.start(); downloadThread2.start(); downloadThread3.start(); } }
Download successful
2.2 steps to implement Runnable interface
.Custom class implementation Runnable Interface .Implement in the interface run()Method, in which the thread execution body is written .Create a thread object and call start()method,Start the thread.
Interpretation of official documents:
2.2.1 RunableDemo
package com.runnable; //Implement the Runnable interface, rewrite the run method, public class MyRunnable implements Runnable { public void run() {//Thread core executor for (int i = 0; i < 20; i++) { System.out.println("Sub thread running:" + i); } } }
public class CommonTest { public static void main(String[] args) { //Create the implementation class object of runnable interface MyRunnable myRunnable = new MyRunnable(); //Thread itself also implements the Runnable interface. Thread thread = new Thread(myRunnable); //Call the start method to start the thread thread.start(); for (int i = 0; i < 50; i++) { System.out.println("Main thread running:" + i); } }
The difference between inheriting Thread class and implementing Runnable interface
* inherit Thread class 1,Subclass inheritance Thread Class has multithreading capability 2,Start thread:Subclass object.start() 3,Not recommended:avoid OOP Limitations of single inheritance. * realization Runable Interface 1,Implementation interface Runnable Multi threading capability 2,Start the thread and pass in the target object+Thread object.start() 3,Recommended use Runnable,It avoids the limitation of single inheritance, is flexible and convenient, and is convenient for the same object to be used by multiple threads.
2.2.2 multi threading to buy train tickets
package com.runnable; //Implement the Runnable interface, rewrite the run method, public class MyRunnable implements Runnable { //votes private int ticket = 100; public void run() {//Thread core executor while (ticket>0) { System.out.println(Thread.currentThread().getName() + "Selling item" + ticket + "Ticket"); //If each thread sells a ticket, one ticket will be deducted ticket--; } } }
public class CommonTest { public static void main(String[] args) { //Thread 1 simulated ticket selling MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); //Thread 2 simulated ticket selling Thread thread2 = new Thread(myRunnable); thread2.start(); //Thread 3 simulated ticket selling Thread thread3 = new Thread(myRunnable); thread3.start(); //Thread 4 simulated ticket selling Thread thread4 = new Thread(myRunnable); thread4.start(); }
console output
Thread-0 The 100th ticket is on sale Thread-0 Ticket 99 is on sale Thread-0 The 98th ticket is on sale Thread-0 The 97th ticket is on sale Thread-0 Ticket 96 is on sale Thread-0 Ticket 95 is on sale Thread-0 Ticket 94 is on sale Thread-3 The 100th ticket is on sale Thread-1 The 100th ticket is on sale Thread-1 Ticket 99 is on sale Thread-1 The 98th ticket is on sale Thread-1 The 97th ticket is on sale Thread-1 Ticket 96 is on sale Thread-1 Ticket 95 is on sale Thread-1 Ticket 94 is on sale Thread-1 Ticket 93 is on sale Thread-1 Ticket 92 is on sale Thread-2 The 100th ticket is on sale Thread-1 Ticket 91 is on sale Thread-3 Ticket 99 is on sale Thread-0 Ticket 93 is on sale
At this time, a problem is found. Thread 0, thread 3 and thread 2 have all sold ticket No. 100, which indicates that when multiple threads operate a resource at the same time, the thread is unsafe and there are serious data problems. This problem will be solved later.
2.3 steps to implement Callable interface
1,realization Callable Interface,Return value type required 2,rewrite call Method, you need to throw an exception 3,Create target object 4,Create execution service: ExecutorService es=new Executors.newFixedThreadPool(1); 5,Submit for execution: Future<Boolean> result=es.submit(1); 6,Get results: boolean flag=result.get(); 7,Shut down service:es.shutdownNow();
2.3.1 implement the Callable interface to download pictures through multiple threads
package com.test; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; /** * Custom download class */ public class WebDownload { //Download method public void downloadFile(String url, String fileName) { try { FileUtils.copyURLToFile(new URL(url), new File(fileName)); } catch (IOException e) { e.printStackTrace(); System.out.println("File download failed"); } } }
package com.callable; import com.test.WebDownload; import java.util.concurrent.Callable; public class MyCallable implements Callable { private String url; private String name; public MyCallable(String url, String name) { this.url = url; this.name = name; } public Boolean call() throws Exception { // WebDownload webDownload = new WebDownload(); //Download the file according to the file url and file name webDownload.downloadFile(url,name); return true; } }
public class CommonTest { public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable myCallable = new MyCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F24%2F20190124212555_aAzHh.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1620823150&t=52bd044f2ba560bfe9ca51bb1b07221e", "zhangjianing2021"); MyCallable myCallable2 = new MyCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F24%2F20190124212555_aAzHh.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1620823150&t=52bd044f2ba560bfe9ca51bb1b07221e", "zhangjianing2022"); MyCallable myCallable3 = new MyCallable("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F24%2F20190124212555_aAzHh.thumb.700_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1620823150&t=52bd044f2ba560bfe9ca51bb1b07221e", "zhangjianing2023"); //Create execution service ExecutorService es = Executors.newFixedThreadPool(3); //Submit for execution Future<Boolean> submit = es.submit(myCallable); Future<Boolean> submit2 = es.submit(myCallable2); Future<Boolean> submit3 = es.submit(myCallable3); //Get results boolean r = submit.get(); boolean r2 = submit2.get(); boolean r3 = submit3.get(); //Shut down service es.shutdown(); }
3. Thread state
Thread states are divided into five states: creation, ready, blocking, running and death.
//Thread execution order Thread thread = new Thread(); 1,Once a thread object is created, it enters a new state 2,call start()Method, the thread is in a ready state, but it does not mean to schedule execution immediately. 3,When called sleep(),wait()Or synchronous locking,The thread entered a blocking state. When the blockage is cleared, Re enter the ready state and wait cpu dispatch. 4,After entering the running state, the thread starts to execute business. 5,Thread death.
3.1 thread core method
//Update thread priority .setPriority(int newPriority); //Hibernates the currently executing thread for the specified number of milliseconds .static void sleep(long millis); //Wait for this thread to terminate / merge threads .void join(); //Pause the thread object currently executing, //And execute other threads, also known as thread comity .static void yield(); //Interrupt the thread, try not to use this method. .void interrupt(); //Test whether the thread is active .boolean isAlive()
3.1 stop / terminate threads
At present, it is not recommended to use the stop() and destroy() methods officially provided by JDK. The document indicates that this method has been abandoned.
More suggestions are to make the thread stop smoothly, such as setting flag bit termination variable.
Example:
public class StopRunnable implements Runnable { //Thread definition stop flag private boolean flag = true; //Provide external thread stopping method public void stop() { this.flag = false; } public void run() { int i =0; //Judgment mark in thread while (flag) { System.out.println(Thread.currentThread().getName()+"Run....."); } } }
public static void main(String[] args) { StopRunnable stopRunnable = new StopRunnable(); Thread thread = new Thread(stopRunnable); thread.start(); for (int i = 0; i < 1000; i++) { System.out.println("Main thread:"+i); if(i==900){ //Call the stop method to switch the identifier and stop the thread stopRunnable.stop(); System.out.println(Thread.currentThread().getName()+":The thread stopped"); } } }
3.2 thread hibernation
1,sleep(long millils)Specifies the number of milliseconds the current thread is blocking 2,sleep There is an exception InteruptedException; 3,sleep When the time reaches, the thread enters the waiting state 4,sleep Can simulate network delay,Countdown, etc. 5,Every object has a lock, but sleep The lock will not be released.
***Ticket selling simulation network delay case
public class Ticket implements Runnable { //votes private static int ticket = 100; public void run() { while (ticket > 0) { try { //Analog delay 2s Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "Thread is selling" + ticket-- + "Ticket"); } } public static void main(String[] args) { Ticket ticket = new Ticket(); Thread thread = new Thread(ticket); Thread thread2 = new Thread(ticket); thread.start(); thread2.start(); } }
****Simulation countdown case
//Simulation countdown Demo public class CountdownTest implements Runnable { private static int num = 10; public void run() { while (num > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("num>>>>>:" + num--); } } public static void main(String[] args) { CountdownTest countdownTest = new CountdownTest(); Thread thread = new Thread(countdownTest); thread.start(); } }
num>>>>>:10 num>>>>>:9 num>>>>>:8 num>>>>>:7 num>>>>>:6 num>>>>>:5 num>>>>>:4 num>>>>>:3 num>>>>>:2 Disconnected from the target VM, address: '127.0.0.1:12167', transport: 'socket' num>>>>>:1
3.3 comity
1,Comity thread, which suspends the thread currently executing, but does not block. 2,Change the thread from running state to ready state 3,Give Way cpu Reschedule,Comity may not succeed,see cpu Mood.
Thread comity Demo
package com.demo; //Thread comity demo public class YieldRunable implements Runnable { public void run() { System.out.println(Thread.currentThread().getName() + "The thread starts executing"); Thread.yield();//Comity thread System.out.println(Thread.currentThread().getName() + "Thread stop execution"); } public static void main(String[] args) { YieldRunable yieldRunable = new YieldRunable(); Thread thread = new Thread(yieldRunable); thread.setName("A"); Thread thread2 = new Thread(yieldRunable); thread2.setName("B"); thread.start(); thread2.start(); } }
3.4 Join merge thread
Join Merge thread,After the execution of this journey, other threads are blocked when executing other threads. Like banks VIP,Or jump the queue. only vip After handling the business, ordinary users can do the business.
Merge thread Join cases
package com.demo; public class JoinRunnable implements Runnable { public void run() { for (int i = 0; i < 1000; i++) { System.out.println("Join>>>>>:" + i); } } public static void main(String[] args) throws InterruptedException { JoinRunnable joinRunnable = new JoinRunnable(); Thread thread = new Thread(joinRunnable); thread.start(); for (int i = 0; i < 100; i++) { if (i == 50) { thread.join();//The main thread is blocked until the vip thread is executed, and then the mian thread is executed } System.out.println("mian>>>>>>>>:" + i); } } }
Sure enough, looking at the console output, when i=50 in mian, the thread is blocked, vip merges (cuts the queue) the thread and completes its own business.
mian>>>>>>>>:0 Join>>>>>:0 Join>>>>>:1 Join>>>>>:2 Join>>>>>:3 Join>>>>>:4 Join>>>>>:5 Join>>>>>:6 Join>>>>>:7 Join>>>>>:8 Join>>>>>:9 mian>>>>>>>>:1 Join>>>>>:10 Join>>>>>:11 Join>>>>>:12 Join>>>>>:13 Join>>>>>:14 mian>>>>>>>>:2 Join>>>>>:15 mian>>>>>>>>:3 Join>>>>>:16 mian>>>>>>>>:4 mian>>>>>>>>:5 mian>>>>>>>>:6 mian>>>>>>>>:7 mian>>>>>>>>:8 mian>>>>>>>>:9 mian>>>>>>>>:10 Join>>>>>:17 Join>>>>>:18 Join>>>>>:19 mian>>>>>>>>:11 mian>>>>>>>>:12 mian>>>>>>>>:13 mian>>>>>>>>:14 mian>>>>>>>>:15 mian>>>>>>>>:16 mian>>>>>>>>:17 mian>>>>>>>>:18 mian>>>>>>>>:19 mian>>>>>>>>:20 mian>>>>>>>>:21 mian>>>>>>>>:22 mian>>>>>>>>:23 mian>>>>>>>>:24 mian>>>>>>>>:25 mian>>>>>>>>:26 mian>>>>>>>>:27 mian>>>>>>>>:28 mian>>>>>>>>:29 mian>>>>>>>>:30 mian>>>>>>>>:31 mian>>>>>>>>:32 mian>>>>>>>>:33 mian>>>>>>>>:34 mian>>>>>>>>:35 mian>>>>>>>>:36 mian>>>>>>>>:37 mian>>>>>>>>:38 Join>>>>>:20 mian>>>>>>>>:39 Join>>>>>:21 mian>>>>>>>>:40 Join>>>>>:22 mian>>>>>>>>:41 Join>>>>>:23 Join>>>>>:24 Join>>>>>:25 Join>>>>>:26 Join>>>>>:27 Join>>>>>:28 Join>>>>>:29 Join>>>>>:30 Join>>>>>:31 Join>>>>>:32 Join>>>>>:33 Join>>>>>:34 Join>>>>>:35 Join>>>>>:36 Join>>>>>:37 mian>>>>>>>>:42 Join>>>>>:38 Join>>>>>:39 Join>>>>>:40 Join>>>>>:41 Join>>>>>:42 Join>>>>>:43 Join>>>>>:44 Join>>>>>:45 Join>>>>>:46 Join>>>>>:47 Join>>>>>:48 mian>>>>>>>>:43 Join>>>>>:49 Join>>>>>:50 Join>>>>>:51 Join>>>>>:52 Join>>>>>:53 Join>>>>>:54 Join>>>>>:55 Join>>>>>:56 Join>>>>>:57 mian>>>>>>>>:44 mian>>>>>>>>:45 mian>>>>>>>>:46 mian>>>>>>>>:47 mian>>>>>>>>:48 mian>>>>>>>>:49 ********************* Join>>>>>:58 ********************* Join>>>>>:.... Join>>>>>:998 Join>>>>>:999 ********************* mian>>>>>>>>:... mian>>>>>>>>:98 mian>>>>>>>>:99
3.5 thread state observation
Thread.State Thread status. A thread can be in one of the following states == New == Threads that have not been started are in this state == RUNNABLE == stay java The state of execution in the virtual machine is in this state == BLOCKED == Threads that are blocked waiting for a monitor lock are in this state == WAITING == A thread that is waiting for another thread to perform a specific action is in this state == TIMED WAITING == The thread that is waiting for another thread to perform the action for the specified waiting time is in this state == TERMINATED == The exited thread is in this state. A thread can be in a state at a given point in time, which does not reflect any operating system thread State of the virtual machine.
Thread status case Demo
package com.demo; public class ThreadState implements Runnable { public void run() { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("///"); } public static void main(String[] args) throws InterruptedException { ThreadState threadState = new ThreadState(); Thread thread = new Thread(threadState); //Observation status NEW Thread.State state = thread.getState(); System.out.println(state); //RUN after thread startup thread.start(); state = thread.getState(); //Run phase System.out.println(state); //If the thread does not stop, it always outputs the state while (state != Thread.State.TERMINATED) { Thread.sleep(100); //Update status state = thread.getState(); // System.out.println(state); } } }
3.6 thread priority
1,Java A thread scheduler is provided to monitor all threads that enter the ready state after startup in the program, The thread scheduler determines which thread should be scheduled to execute according to priority. 2,The priority of threads is expressed in numbers, ranging from 1~10 2.1 Thread.MIN_PRIORITY=1 2.2 Thread.MAX_PRIORITY=10 2.3 Thread.NORM_PRIORITY=5 Use the following methods to change or obtain priority ... getPriority().setPriority(int xxx)
Thread priority case Demo
package com.demo; /** * thread priority */ public class ThreadPriority implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + "....>>>" + Thread.currentThread().getPriority()); } public static void main(String[] args) { //Default priority of main thread System.out.println(Thread.currentThread().getName() + "....>>>" + Thread.currentThread().getPriority()); ThreadPriority threadPriority = new ThreadPriority(); Thread thread = new Thread(threadPriority); Thread thread2 = new Thread(threadPriority); Thread thread3 = new Thread(threadPriority); Thread thread4 = new Thread(threadPriority); Thread thread5 = new Thread(threadPriority); Thread thread6 = new Thread(threadPriority); //Set priority first and then start thread.start(); thread2.setPriority(1); thread2.start(); thread3.setPriority(4); thread3.start(); //MAX_PRIORITY =10 thread4.setPriority(Thread.MAX_PRIORITY); thread4.start(); thread5.setPriority(-1); thread5.start(); thread6.setPriority(11); thread6.start(); } }
The console reports an error. At this time, it shows that the low priority of threads only means that the probability of obtaining scheduling is low,
It is not that it will not be called if the priority is low. It depends on the CPU scheduling.
Thread-0....>>>5 Thread-1....>>>1 Thread-2....>>>4 Thread-3....>>>10 java.lang.IllegalArgumentException at java.lang.Thread.setPriority(Thread.java:1089) at com.demo.ThreadPriority.main(ThreadPriority.java:34)
3.7 daemon
1,Threads are divided into user threads and daemon threads 2,The virtual machine must ensure that the user thread has completed execution 3,The virtual machine does not have to wait for the daemon thread to finish executing, Such as background recording operation log, monitoring memory, garbage collection, etc..
Daemon case Demo
package com.demo; /** * Daemon thread */ public class ThreadDaemon { public static void main(String[] args) { God god = new God(); Perople perople = new Perople(); Thread thread = new Thread(god); //The default false indicates that the user thread is normal, and all threads are user threads thread.setDaemon(true); //God starts the daemon thread thread.start(); Thread thread2 = new Thread(perople); //User thread start thread2.start(); } } class God implements Runnable { @Override public void run() { while (true) { System.out.println("Oh, my God, bless the people"); } } } class Perople implements Runnable { @Override public void run() { for (int i = 0; i < 36500; i++) { System.out.println("People live happily every day"); } System.out.println("====googbybe world ==="); } }
3.8 concurrency
Concurrency: the same object or resource is operated by multiple threads at the same time. Such as grabbing tickets, withdrawing money from two banks at the same time, sharing printers, or eating in the school restaurant.
Causes of thread insecurity: **Because multiple threads of the same process share the same storage space, it brings convenience as well as convenience The problem of access conflict is solved. In order to ensure the correctness of data being accessed in the method, it is added when accessing Lock mechanism synchronized,When a thread obtains the exclusive lock of an object and monopolizes resources, other threads You must wait and release the lock after use. There are the following problems 1,All threads that need this lock will hang. 2,In multi-threaded competition, locking and releasing locks will lead to more context switching and scheduling delays, Cause performance problems. 3,If a high priority thread waits for a low priority thread to release the lock(For example, a toilet, The high priority is just urinating, while the low priority is diarrhea, occupying the door latch resources, Only those with low priority can release the lock, and those with high priority can urinate. They may pee their pants) This will cause priority and performance problems.
.
When dealing with multithreading, when multiple threads access the same object and some threads want to modify the object, we need thread synchronization. Thread synchronization is actually a waiting mechanism. Multiple threads that need to access the object at the same time enter the waiting pool of the object and form a queue (relative to the queue), waiting for the previous threads to be used up, The next thread is reused.
#Simulate the unsafe case of multi-threaded ticket purchase under concurrency
//Reproduce thread insecurity public class TicketRunnable implements Runnable { private int ticket = 100; @Override public void run() { while (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":Selling item" + ticket-- + ":ticket"); } } public static void main(String[] args) { TicketRunnable ticketRunnable = new TicketRunnable(); Thread thread = new Thread(ticketRunnable); Thread thread2 = new Thread(ticketRunnable); Thread thread3 = new Thread(ticketRunnable); thread.start(); thread2.start(); thread3.start(); } }
At this time, the three threads share the socket variable, and problems occur in parallel (the same ticket is sold, or even a negative ticket), such as console printing
Thread-1:Selling 100th:ticket Thread-2:Selling 100th:ticket Thread-0:Selling 100th:ticket Thread-2:Selling 99th:ticket Thread-1:Selling 99th:ticket Thread-2:Selling 98th:ticket Thread-0:Selling 99th:ticket Thread-2:Selling 97th:ticket Thread-1:Selling 98th:ticket Thread-2:Selling 96th:ticket Thread-0:Selling 98th:ticket Thread-2:Selling 95th:ticket Thread-1:Selling 97th:ticket Thread-2:Selling 94th:ticket Thread-0:Selling 97th:ticket ...................... Thread-2:Selling item-1:ticket
Thread unsafe collection cases
public class UnsafeCollection { public static void main(String[] args) { //Thread unsafe collection List<String> list = new ArrayList<>(); for (int i = 0; i < 10000; i++) { new Thread(() -> { list.add(Thread.currentThread().getName()); }).start(); System.out.println(list.size()); } } }
There are only 9996 console outputs.
9996
4 solve and issue thread insecurity.
4.1 synchronization method
1,Because we can pass private Keyword to ensure that data objects can only be accessed by methods,So we We only need to propose a set of mechanism for the method,This mechanism is synchronized keyword Syntax: public synchronized void method(int args){} synchronized Method control pair"object"That is, each object corresponds to a lock, each synchronized Methods must obtain the lock of the object calling the method in order to execute,Otherwise, the thread is blocked, Once the method is executed,It monopolizes the lock and does not release the lock until the method returns,Only later blocked threads can Get this lock and continue. Prerequisites for synchronization: 1, There must be two or more threads 2,Multiple threads must use the same lock. Disadvantages of synchronization method: If you declare a large method as synchronized It will affect efficiency (multiple threads need to judge locks, which consumes more resources).
The ticket selling problem can be solved at this time
ublic class Ticket implements Runnable { private static int ticket = 100; public void run() { buyTicket(); } public synchronized void buyTicket() { while (ticket > 0) { try { //Analog delay 2s //Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "Thread is selling" + ticket-- + "Ticket"); } } public static void main(String[] args) { Ticket ticket = new Ticket(); Thread thread = new Thread(ticket); Thread thread2 = new Thread(ticket); Thread thread3 = new Thread(ticket); Thread thread4 = new Thread(ticket); thread.start(); thread2.start(); thread3.start(); thread4.start(); } }
4.2 synchronization code block
Syntax: synchnronized(Obj){} 1,Obj be called ==Synchronization monitor==Lock object .Objects are like locks. Threads that hold locks can synchronize. There is no thread holding the lock, even if it is obtained CPU Can't get in because there is no lock. Obj Can be any object, but is strongly recommended==shared resource==As a synchronization monitor. The so-called shared resources refer to the objects of addition, deletion and modification. It doesn't matter if you query. There is no need to specify a synchronization monitor in the synchronization method, because the synchronization monitor in the synchronization method is this, That is, the object itself, or.class 2,Synchronization monitor execution process 2.1 The first thread accesses, locks the synchronization monitor, and executes business logic 2.2 The second thread accesses and finds that the synchronization monitor is locked and cannot be accessed 2.3 After the first thread is executed, unlock the synchronization monitor and release the lock resources 2.4 The second thread accesses and finds that there is no lock. It grabs the lock resource and locks and accesses it 2.5
Now you can use synchronized code blocks to solve the thread unsafe collection problem just now
public class UnsafeCollection { public static void main(String[] args) { List<String> list = new ArrayList<>(); for (int i = 0; i < 10000; i++) { new Thread(() -> { //Locked the resources shared by all threads synchronized (list) { list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
Similarly, the synchronization code block can solve the unsafe problem of ticket selling
public class TicketRunnable implements Runnable { private int ticket = 100; Object object = new Object(); @Override public void run() { while (true) { synchronized (object) { if (ticket > 0) { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":Selling item" + ticket-- + ":ticket"); } } } } public static void main(String[] args) { TicketRunnable ticketRunnable = new TicketRunnable(); Thread thread = new Thread(ticketRunnable); Thread thread2 = new Thread(ticketRunnable); Thread thread3 = new Thread(ticketRunnable); Thread thread4 = new Thread(ticketRunnable); Thread thread5 = new Thread(ticketRunnable); thread.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); } }
5 deadlock
Multiple threads occupy some shared resources and wait for the resources occupied by other threads to run. As a result, two or more threads are waiting for each other to release resources and stop execution. For example, when a synchronous code block has locks on more than two objects, deadlock may occur.
5.1 deadlock avoidance method
Four necessary conditions for deadlock 1,Mutex condition: a resource can only be used by one process at a time. 2,Request and hold condition: when a process is blocked by requesting resources,Hold on to the resources you have obtained. 3,Conditions of non deprivation: the resources obtained by the process cannot be forcibly deprived before they are used up. 4,Circular waiting condition: a circular waiting resource relationship is formed between several processes.
All said that as long as we find a way to crack any one or more of these conditions, we can avoid deadlock.
6 Lock lock
1,from JDK5.0 start,Java Provides a more powerful thread synchronization mechanism--Define synchronization lock objects through display To achieve synchronization, synchronization lock is used Lock Objects act as. 2,java.util.concurrent.locks.Lock Interface is to control multiple threads to share resources Tools to access. Locks provide exclusive access to shared resources, with only one thread pair at a time Lock Object locking, A thread should obtain a password before starting to access a shared resource Lock Object. 3,ReentrantLock Class implements Lock,It has and synchronized Same concurrency Memory semantics,In the control of thread safety,More commonly used is ReentrantLock, You can display locking and releasing locks.
/** * lock Lock solves thread safety problems */ public class ReentrantLockTest implements Runnable { private ReentrantLock lock = new ReentrantLock(); private int ticket = 1000; @Override public void run() { while (true) { try { lock.lock(); if (ticket > 0) { try { //Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } // while (ticket > 0) { System.out.println(Thread.currentThread().getName() + ": On sale" + ticket-- + "Ticket"); // } } else { break; } } finally { lock.unlock(); } } } public static void main(String[] args) { ReentrantLockTest reentrantLockTest = new ReentrantLockTest(); Thread thread = new Thread(reentrantLockTest); Thread thread2 = new Thread(reentrantLockTest); Thread thread3 = new Thread(reentrantLockTest); Thread thread4 = new Thread(reentrantLockTest); thread.start(); thread2.start(); thread3.start(); thread4.start(); }
7 difference between synchronized and Lock
1,Lock Show lock when locking(Manually open and close the lock),synchronized It's a hidden test, The scope will be released automatically. 2,Lock Only code block locks,synchronized There are code block locks and method locks 3,use Lock Lock, Jvm It will take less time to schedule threads, with better performance and better scalability (Provide more subclasses) 4,Limited use steps Lock>Synchronous code block(Has entered the method body,Corresponding resources are allocated)>Synchronization method (outside the method body)
9 thread collaboration (producer consumer mode)
9.1 thread communication
Application scenario: producer and consumer issues
If only one product can be stored in the warehouse, the producer will put the produced products into the warehouse, and the consumer will take away the products in the warehouse for consumption.
If there is no product in the warehouse, the producer will put the product into the warehouse, otherwise stop production and wait until the product in the warehouse is taken away by the consumer.
If the product is placed in the warehouse, the consumer can take the product away for consumption, otherwise stop consumption and wait until the product is placed in the warehouse again.
9.2 thread communication - Analysis
This is a thread synchronization problem. Producers and consumers share the same resource,And between producers and consumers Interdependent and conditional. 1,For producers, consumers should be informed to wait before producing products, and after producers produce products, It is necessary to inform consumers of consumption immediately. 2,For consumers, after consumers, they should inform producers that they have finished consumption and need to produce new products For consumption. 3,In the producer consumer problem, only synchronized It's not enough, 3.1 synchronized Prevents concurrent updates to the same shared resource,Synchronization is realized. 3.2 synchronized It cannot be used to realize message passing between different threads(signal communication)
9.3 = = thread communication method==
java Several methods are provided to solve the communication problem between threads 1,wait() : Indicates that the thread waits until notified by other threads, and sleep Different, the lock will be released 2,wait(long timeout): Specifies the number of milliseconds to wait 3,notify(): Wake up a waiting thread 3,notifyAll(): Wake up all calls on the same object wait()Method, with high priority Thread priority scheduling They are all parents Object All methods can only be used in synchronization methods or synchronization code blocks, otherwise Will throw IIIegalMonitorStateException
9.4 thread communication mode - pipe method
Concurrent collaboration model "producer"/"Consumer" -->Pipe program method Producer: the module responsible for production data (may be method, object, thread, process) consumer:Module responsible for processing data Buffer: consumers cannot use the producer's data directly,There's a buffer between them, The producer puts the produced data into the buffer, and the consumer takes out the data from the buffer
Producer / consumer model - > case of pipe process method
10 thread pool
Why use thread pools? reason:Frequently create and destroy resources that are heavily used, such as threads in concurrency,It has a great impact on performance. Solution ideas:Create multiple threads in advance,Put into thread pool,Get it directly when you use it, and put it back into the pool after use. sure Avoid frequent creation, destruction and reuse. Similar to transportation in life. advantage: 1,Improve response speed(Reduced time to create new threads) 2,Reduce resource consumption(Reuse threads in thread pool,You don't need to create it every time) 3,Easy thread management .corePoolSize:Size of core pool .maximumPoolSize:Maximum number of threads .keepAliveTime:How long does the thread last when there is no task
10.1 use of wire path pool
JDK5. From 0 onwards, thread pool related API s are provided: ExcutorService and Executors
ExcutorService: real thread pool interface, subclass ThreadPoolExecutor
void execute(Runnable command):Perform tasks/Command, no return value, Generally used to perform Runnable <T>Futrue<T>submit(Callable<T>task):Perform tasks,There is a return value,Generally used implement Callable void shutdown():Close connection pool Executors:Factory class of tool class and thread class,Used to create and return different types of thread pools
10.1 case of linear process pool
public class ExecutorsTest { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); executorService.execute(new ThreadTest()); executorService.execute(new ThreadTest()); executorService.execute(new ThreadTest()); executorService.execute(new ThreadTest()); executorService.shutdown(); } } class ThreadTest implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }