Catalog
4.1.1 inherits the Thread class (emphasis)
4.1.2 Implementing Runnable Interface (Key)
4.1.3 Implement callable interface (Understanding)
4.2.5 Thread State Observation
5.2 Synchronization Method and Synchronization Block
5.2.1 Supplement: Thread Security Collection CopyOnWriteArrayList
8 Producer and consumer issues
Crazy Video: [Crazy Java] Multithreaded Details_ Bell-Bell-Bell_ bilibili
Multithreaded
1 Overview
1.1 Tasks
_There are too many examples of doing many things at the same time in reality. It seems that many tasks are being done at the same time. In fact, our brains still do only one thing at the same time.
1.2 Process
_Programs running in the operating system are processes, such as your QQ, player, game, IDE and so on.
_A process can have multiple threads, such as listening to sound, viewing images, watching marquees, etc. in a video at the same time
_1. When it comes to processes, you have to talk about procedures. A program is an ordered collection of instructions and data that has no meaning to run and is a static concept. _2. A process is an execution process of a program and it is a dynamic concept. Is the unit of system resource allocation_3. Usually a process can contain several threads, of course a process has at least one thread, otherwise it has no meaning. Threads are the units of CPU scheduling and execution.
Note: Many multithreads are simulated. True multithreading refers to having multiple CPUs, that is, multicores, such as servers. In the case of simulated multithreading, that is, in the case of a single cpu, the cpu can only execute one code at a time because the switch is fast, so there is an illusion of simultaneous execution.
Summary:1. Threads are independent execution paths; _2. When a program is running, there will be multiple threads in the background, such as the main thread and the gc thread, even if there is no thread created by itself. _3.main() is called the main thread, which is the entrance to the system and is used to execute the whole program. _4. In a process, if multiple threads are opened up, the running of threads is scheduled by a dispatcher (CPU), which is closely related to the operating system and cannot be interfered with artificially in sequence. _5. When operating on the same resource, there will be a problem of resource seizure, which requires concurrency control. _6. Threads incur additional overhead, such as CPU scheduling time and concurrency control overhead. _7. Each thread interacts in its own working memory, and improper memory control can cause data inconsistencies;
1.3 Multithreaded
Common method calls and multithreading
2 Static Proxy
package com.yw; public class StaticProxy { public static void main(String[] args) { WeddingComapny weddingComapny=new WeddingComapny(new You()); weddingComapny.HappyMarrt(); } } interface Marry{ void HappyMarrt(); } //Real Role class You implements Marry{ @Override public void HappyMarrt() { System.out.println("Get married..."); } } //delegable role class WeddingComapny implements Marry{ private Marry target; public WeddingComapny(Marry target) { this.target = target; } @Override public void HappyMarrt() { before(); this.target.HappyMarrt(); after(); } private void after(){ System.out.println("Settlement"); } private void before(){ System.out.println("Before you get married, set up the scene"); } }
Result
Before you get married, set up the scene Get married... Settlement
Static proxy summary:1. Both real objects and proxy objects need to implement the same interface_2. Proxy objects need to proxy real role benefits:Proxy objects can do many things that objects can't do_Real objects focus on doing their own things
3 Lamda expression
_The eleventh letter in the Greek alphabet, named Lambda in English to avoid overdefining internal classes_It is essentially a functional programming concept
(params) -> expression [Expression] (params) -> statement [Sentence] (params) -> {statement } 123 new Thread(()-> System.out.println("Multithreaded Learning")).start(); 1
Why use lambda expressions_1.Avoid overdefining your internal classes_2.Make your code look concise_3.Remove a lot of meaningless code, leaving only the core logic behind
Definition of a functional interface_1. Any interface that contains only one abstract method is a functional interface. _2. For a functional interface, we can create an object for that interface through a lambda expression.
General Writing
package com.yw; //Derive lambda expression public class TestLambda1 { //3 Static internal class static class Like2 implements ILike{ @Override public void lambda() { System.out.println("i like lambda2"); } } public static void main(String[] args) { ILike like=new Like(); like.lambda(); like=new Like2(); like.lambda(); //4 Local internal classes class Like3 implements ILike{ @Override public void lambda() { System.out.println("i like lambda3"); } } like=new Like3(); like.lambda(); //5 Anonymous internal class has no class name and must be supported by an interface or parent class like =new ILike() { @Override public void lambda() { System.out.println("i like lambda4"); } }; //6 lambda simplification like=()->{ System.out.println("i like lambda5"); }; like.lambda(); } } //1 interface interface ILike{ void lambda(); } //Implementation Class class Like implements ILike{ @Override public void lambda() { System.out.println("i like lambda"); } }
To parameters
package com.yw; public class TestLambda2 { public static void main(String[] args) { ILove love=(int a)->{ System.out.println("i love you1-->"+a); }; //Simplify 1 de-parameter type love=(a)->{ System.out.println("i love you1-->"+a); }; //Simplify 2 () love=a -> { System.out.println("i love you1-->"+a); }; //Simplify 3 //Summary: A lambda expression can be simplified to one line only if it has one line of code, and if it has more than one line, it is wrapped in a code block. //The precondition is that the interface is a functional interface love=a-> System.out.println("i love you1-->"+a); love.love(5); } } interface ILove{ void love(int a); } class Love implements ILove{ @Override public void love(int a) { System.out.println("i love you1-->"+a); } }
4 Threads
4.1 Thread Creation
4.1.1 inherits the Thread class (emphasis)
package com.yw.demo01; //Create threads by inheriting the Thread class public class TestThead extends Thread{ @Override public void run() { for (int i=0;i<20;i++){ System.out.println("I'm looking at the code---"+i); } } public static void main(String[] args) { TestThead testThead=new TestThead(); //Call the start() method to open the thread //testThead.start(); testThead.run(); for (int i=0;i<20;i++){ System.out.println("I am learning multithreading---"+i); } } }
Summary
Calling run() executes the run method first, synchronously
The start method is the default execution entry for the Thread class. When the start method is called, it means that the Thread starts execution and really implements multithreading.
Case Network Diagram Download
1 Import jar package commons-io-2.6,jar
package com.yw.demo01; //Create threads by inheriting the Thread class public class TestThead extends Thread{ @Override public void run() { for (int i=0;i<20;i++){ System.out.println("I'm looking at the code---"+i); } } public static void main(String[] args) { TestThead testThead=new TestThead(); //Call the start() method to open the thread //testThead.start(); testThead.run(); for (int i=0;i<20;i++){ System.out.println("I am learning multithreading---"+i); } } }
4.1.2 Implementing Runnable Interface (Key)
package com.yw.demo01; //Implement Runnable Interface public class TestThread3 implements Runnable{ @Override public void run() { for (int i=0;i<20;i++){ System.out.println("I'm looking at the code---"+i); } } public static void main(String[] args) { TestThread3 testThead3=new TestThread3(); //Create Thread Object Thread thread=new Thread(testThead3); //Call the start() method to open the thread thread.start(); for (int i=0;i<20;i++){ System.out.println("I am learning multithreading---"+i); } } }
Summary
Recommended Use: Avoid single inheritance limitations, be flexible and convenient, and allow multiple threads to use the same object
case
package com.yw.demo01; //Multiple threads operate on the same object //Example of buying a train ticket public class TestThread4 implements Runnable{ private int titckNum=10; @Override public void run() { while (true){ if (titckNum<=0){ break; } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"-->Get the first"+titckNum--+"Tickets"); } } public static void main(String[] args) { TestThread4 ticket=new TestThread4(); new Thread(ticket,"Xiao Ming").start(); new Thread(ticket,"Teacher").start(); new Thread(ticket,"Daniel").start(); } }
Result
Daniel-->Get the 10th ticket Teacher-->Got the ninth ticket Xiao Ming-->Get the eighth ticket Teacher-->Get the 7th ticket Xiao Ming-->Get the sixth ticket Daniel-->Get the 5th ticket Daniel-->Get the fourth ticket Xiao Ming-->Get the third ticket Teacher-->Get the second ticket Xiao Ming-->Get the first ticket Daniel-->Got ticket 0 Teacher-->Get the first ticket
Case study: tortoise-rabbit race
package com.yw.demo01; //Simulate tortoise-rabbit race public class Race implements Runnable{ //Winner private static String winner; @Override public void run() { for (int i = 0; i <=100 ; i++) { //Simulate rabbit rest if (Thread.currentThread().getName().equals("Rabbit") && i%10==0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } boolean flag=gameOver(i); if (flag){ break; } System.out.println(Thread.currentThread().getName()+"-->Run"+i+"step"); } } //Determine if you have finished the game private boolean gameOver(int steps){ if (winner!=null){ //There is already a winner, the game is over return true; } if (steps>=100){ winner=Thread.currentThread().getName(); System.out.println("winner is"+winner); return true; } return false; } public static void main(String[] args) { Race race=new Race(); new Thread(race,"Rabbit").start(); new Thread(race,"Tortoise").start(); } }
Result
<span style="background-color:#f8f8f8"><span style="color:#333333 ">Rabbit-->0 Runs Rabbit-->1 run Rabbit-->2 runs Rabbit-->Run three runs Rabbit-->Run 4 Steps Rabbit-->5 runs Rabbit-->Run 6 Steps Rabbit-->Seven runs Rabbit-->8 runs Rabbit-->9 runs Tortoise-->Run 0 steps Tortoise-->1 run Tortoise-->2 runs Tortoise-->Run three runs Tortoise-->Run 4 Steps Tortoise-->5 runs Tortoise-->Run 6 Steps Tortoise-->Seven runs Tortoise-->8 runs Tortoise-->9 runs Tortoise-->10 runs Tortoise-->11 runs Tortoise-->12 runs Tortoise-->13 runs Tortoise-->14 runs Tortoise-->15 runs Tortoise-->16 runs Tortoise-->17 runs Tortoise-->18 runs Tortoise-->19 runs Tortoise-->20 runs Tortoise-->Running 21 steps Tortoise-->22 runs Tortoise-->23 runs Tortoise-->24 runs Tortoise-->25 runs Tortoise-->26 runs Tortoise-->27 runs Tortoise-->28 runs Tortoise-->29 runs Tortoise-->Run 30 steps Tortoise-->Run 31 steps Tortoise-->Run 32 steps Tortoise-->Run 33 steps Tortoise-->Run 34 steps Tortoise-->Run 35 steps Tortoise-->Run 36 steps Tortoise-->37 runs Tortoise-->Run 38 steps Tortoise-->Run 39 steps Tortoise-->Run 40 steps Tortoise-->Run 41 steps Tortoise-->Run 42 steps Tortoise-->Run 43 steps Tortoise-->Run 44 steps Tortoise-->Run 45 steps Tortoise-->46 runs Tortoise-->47 runs Tortoise-->Run 48 steps Tortoise-->Run 49 steps Tortoise-->50 runs Tortoise-->51 runs Tortoise-->52 runs Tortoise-->53 runs Tortoise-->54 runs Tortoise-->55 runs Tortoise-->56 runs Tortoise-->57 runs Tortoise-->58 runs Tortoise-->59 runs Tortoise-->Running 60 steps Tortoise-->Run 61 steps Tortoise-->Running 62 steps Tortoise-->Run 63 steps Tortoise-->Run 64 steps Tortoise-->Running 65 steps Tortoise-->Running 66 steps Tortoise-->67 runs Tortoise-->68 runs Tortoise-->Running 69 steps Tortoise-->70 runs Tortoise-->71 runs Tortoise-->72 runs Tortoise-->73 runs Tortoise-->74 runs Tortoise-->75 runs Tortoise-->76 runs Tortoise-->77 runs Tortoise-->78 runs Tortoise-->79 runs Tortoise-->Running 80 steps Tortoise-->Run 81 steps Tortoise-->82 runs Tortoise-->83 runs Tortoise-->84 runs Tortoise-->Running 85 steps Tortoise-->86 runs Tortoise-->87 runs Tortoise-->88 runs Tortoise-->89 runs Tortoise-->Running 90 steps Tortoise-->91 runs Tortoise-->92 runs Tortoise-->93 runs Tortoise-->94 runs Tortoise-->95 runs Tortoise-->96 runs Tortoise-->97 runs Tortoise-->98 runs Tortoise-->99 runs winner is Tortoise</span></span>
4.1.3 Implement callable interface (Understanding)
-
To implement the callable interface, a return value type is required
-
Override call method, need to throw exception
-
Create Target Object
-
Create an execution service: ExecutorService ser=Executors.newFixedThreadPool(1);
-
Commit execution: Future<Boolean>result1=ser.submit(1);
-
Get the result: boolean r1=result1.get();
-
Shut down service: ser,shutdowmNow();
package com.yw.demo02; import com.yw.demo01.TestThread2; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; //Implement Callable public class TestCallable implements Callable { private String url; //Web Picture Address private String name;//Saved file name public TestCallable(String url,String name){ this.url=url; this.name=name; } @Override public Object call() throws Exception { WebDownLoader webDownLoader=new WebDownLoader(); webDownLoader.downloader(url,name); System.out.println("Downloaded file name:"+name); return true; } //Downloader class WebDownLoader{ //Download Method public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO Exceptions, downloader Method problem"); } } } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable t1=new TestCallable("https://img-pre.ivsky.com/img/tupian/pre/202104/13/maomi_youzai-002.jpg","1.jpg"); TestCallable t2=new TestCallable("https://img-pre.ivsky.com/img/tupian/pre/202104/13/maomi_youzai-002.jpg","2.jpg"); TestCallable t3=new TestCallable("https://img-pre.ivsky.com/img/tupian/pre/202104/13/maomi_youzai-002.jpg","3.jpg"); //Create Execution Service ExecutorService ser= Executors.newFixedThreadPool(3); //Submit Execution Future<Boolean> r1=ser.submit(t1); Future<Boolean> r2=ser.submit(t2); Future<Boolean> r3=ser.submit(t3); //Get results Boolean rs1 = r1.get(); Boolean rs2 = r2.get(); Boolean rs3 = r3.get(); //Shut down services ser.shutdownNow(); } }
Result
<span style="background-color:#f8f8f8"><span style="color:#333333 "> Downloaded file name: 1.jpg Downloaded file named:3.jpg Downloaded file named:2.jpg</span></span>
Summary:
Return values can be defined
Exceptions can be thrown
4.2 Thread State
Five States
4.2.1 Stop Thread
-
stop(), destroy() methods are not recommended
-
Recommend that the thread stop itself
-
It is recommended that you use a flag bit to terminate the variable and terminate the thread when flag=false.
package com.yw.state; /** * - stop(), destroy() methods are not recommended * * - Recommend that the thread stop itself * * - It is recommended that you use a flag bit to terminate the variable and terminate the thread when flag=false. */ public class TestStop implements Runnable{ private boolean flag=true; @Override public void run() { int i=0; while (flag){ System.out.println("run....Thread"+i++); } } public void stop(){ this.flag=false; } public static void main(String[] args) { TestStop testStop=new TestStop(); new Thread(testStop).start(); for (int i = 0; i <1000 ; i++) { System.out.println("main"+i); if (i==900){ testStop.stop(); System.out.println("Thread stopped"); } } } }
4.2.2 Thread Hibernates
-
Sleep (time) specifies the number of milliseconds the current thread is blocking 1000ms=1s
-
The sleep has an exception InterruptedException;
-
Thread is ready when sleep time arrives
-
sllep can simulate network latency, countdown, etc.
-
Every object has a lock, sleep does not release the lock
package com.yw.state; import java.text.SimpleDateFormat; import java.util.Date; //Analog countdown public class TestSleep2{ public static void main(String[] args) { // try { // tenDown(); // } catch (InterruptedException e) { // e.printStackTrace(); // } //Print the current system time Date startTime=new Date(System.currentTimeMillis()); while (true){ try { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime)); startTime=new Date(System.currentTimeMillis());//Update current time } catch (InterruptedException e) { e.printStackTrace(); } } } //Analog countdown public static void tenDown () throws InterruptedException{ int num=10; while (true){ Thread.sleep(1000); System.out.println(num--); if (num<=0){ break; } } } }
4.2.3 Thread yield
-
Causes the thread to pause, but not block, the currently executing thread
-
Change Thread from Running to Ready
-
Let cpu reschedule, comity may not succeed, see cpu mood
package com.yw.state; public class TestYield { public static void main(String[] args) { MyYield myYield=new MyYield(); new Thread(myYield,"a").start(); new Thread(myYield,"b").start(); } } class MyYield implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName() + "Thread Starts Execution"); Thread.yield(); System.out.println(Thread.currentThread().getName() + "Thread Stops Execution"); } }
4.2.4 Thread Enforcement
-
Join merges threads and waits until this thread finishes before executing other threads, which are blocked
-
Imagine jumping in the queue
package com.yw.state; public class TestJoin implements Runnable{ public static void main(String[] args) throws InterruptedException { TestJoin testJoin=new TestJoin(); Thread thread=new Thread(testJoin); thread.start(); for (int i = 0; i <1000 ; i++) { if (i==200){ thread.join();//Queue Break } System.out.println("main"+i); } } @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("thread vip Coming"+i); } } }
4.2.5 Thread State Observation
public static enum Thread.State
Thread state, Threads can be in one of the following states: NEW_not yet started thread is in this state RUNNABLE_executed thread in Java virtual machine is in this state BLOCKED_blocked thread waiting for monitor lock is in this state WAITING_waiting for another thread to perform a specific action TIMED WAITING_waiting for another thread in this state Threads whose process execution action reaches the specified wait time are in this state TERMINATED_Exited threads are in this state
_A thread can be in a state at a given point in time, which does not reflect the virtual machine state of any operating system thread state.
package com.yw.state; //Observing test thread state public class TestState { public static void main(String[] args) throws InterruptedException { Thread thread=new Thread(()->{ for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("/"); } }); //Observed state Thread.State state=thread.getState(); System.out.println(state); //After observation starts thread.start(); state=thread.getState(); System.out.println(state); while (state!=Thread.State.TERMINATED){//Output status as long as it does not terminate Thread.sleep(100); state=thread.getState();//Update thread state System.out.println(state); } } }
output
<span style="background-color:#f8f8f8"><span style="color:#333333">NEW RUNNABLE TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING / TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING / TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING / TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING / TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING TIMED_WAITING / TERMINATED Process finished with <span style="color:#770088">exit</span> code <span style="color:#116644">0</span> </span></span>
4.3.6 Priority
-
Java provides a thread dispatcher to monitor all threads that are ready after startup in the program. Thread dispatcher installation priority determines which thread should be dispatched to execute.
-
Thread priority is represented numerically and ranges from 1 to 10 Thread.MIN_PRIORITY = 1; Thread.MAX_PRIORITY = 10; _Thread.NOPM_PRIORITY = 5;
Change or get priority_getPriority() setPriority(int xx) by
package com.yw.state; //Test Priority public class TestPriority{ public static void main(String[] args) { //Main Thread Default Priority System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); MyPriority myPriority=new MyPriority(); Thread t1 = new Thread(myPriority); Thread t2 = new Thread(myPriority); Thread t3 = new Thread(myPriority); Thread t4 = new Thread(myPriority); Thread t5 = new Thread(myPriority); Thread t6 = new Thread(myPriority); //Set priority first, at startup t1.start(); t2.setPriority(1); t2.start(); t3.setPriority(4); t3.start(); t4.setPriority(Thread.MAX_PRIORITY); t4.start(); t5.setPriority(8); t5.start(); t6.setPriority(7); t6.start(); } } class MyPriority implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority()); } }
Result
<span style="background-color:#f8f8f8"><span style="color:#333333">main-->5 Thread-3-->10 Thread-4-->8 Thread-5-->7 Thread-0-->5 Thread-2-->4 Thread-1-->1 Process finished with <span style="color:#770088">exit</span> code <span style="color:#116644">0</span> </span></span>
4.3.7 Thread Daemon
-
Threads are divided into user threads and daemon threads
-
Virtual machines must ensure that user threads are executed
-
The virtual machine does not have to wait for the daemon thread to finish executing
-
For example: background record operation log, monitor memory, garbage collection and so on...
package com.yw.state; public class TestDaemon { public static void main(String[] args) { God god=new God(); You you=new You(); Thread thread=new Thread(god); thread.setDaemon(true); //The default false indicates a user process, and normal threads are user threads thread.start();//Daemon thread startup new Thread(you).start();//User Thread Start } } //lord class God implements Runnable{ @Override public void run() { while (true){ System.out.println("----God-----"); } } } //you class You implements Runnable{ @Override public void run() { for (int i = 0; i <36500 ; i++) { System.out.println("Alive"+i+"day"); } System.out.println("#########bye##########"); } }
5-Thread Synchronization
Multiple threads operate on the same resource
Concurrency: The same object is operated on simultaneously by multiple threads
_In real life, we will encounter the problem of "the same resource, many people want to use". For example: the canteen queues for dinner, everyone wants to eat, the most natural solution is to queue. One by one
When dealing with multithreading problems, multiple threads access the same object (concurrently) and some threads want to modify it. Thread synchronization is a mechanism in which multiple threads that need to access this object at the same time enter the waiting pool of this object to form a queue, waiting for the previous thread to finish using it, and the next thread to use it again.
5.1 Queues and Locks
_Because multiple threads of the same process share the same storage space, which brings convenience and access conflicts. In order to ensure the correctness of data access in the method, synchronized lock mechanism is added when accessing. When a thread acquires exclusive locks on objects and exclusive resources, other threads must wait and release the locks after use. There are the following problems:1. A thread with a lock can cause other threads needing the lock to hang; _2. Under multithreaded competition, unlocking and releasing locks can cause more context switching and scheduling delays, causing performance problems; _3. If a higher priority thread waits for a lower priority thread to release the lock, the priority will be inverted, causing performance problems.
Thread Insecurity Case 1: Insecure Buying
package com.yw.syn; public class UnsafeBuyTicket { public static void main(String[] args) { BuyTicket buyTicket=new BuyTicket(); new Thread(buyTicket,"a").start(); new Thread(buyTicket,"b").start(); new Thread(buyTicket,"c").start(); } } class BuyTicket implements Runnable{ private int ticketNumm=10; boolean flag=true; @Override public void run() { while (true){ buy(); } } private void buy(){ if (ticketNumm<=0){ flag=false; return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //Buy tickets System.out.println(Thread.currentThread().getName()+"Get it"+ticketNumm--); } }
Result
<span style="background-color:#f8f8f8"><span style="color:#333333 ">c gets 10 b Get 9 a Get 8 a Get 7 b Get 6 c Get 5 a Get 4 c Get 3 b Get 3 c Get 2 b Get 1 a Get 0 c Get it-1 </span></span>
Result appears -1
Thread insecurity case 2: Bank withdrawal
package com.yw.syn; public class UnsafeBank { public static void main(String[] args) { Account account=new Account(100,"Travel Fund"); Drawing you=new Drawing(account,50,"you"); Drawing xiaoming=new Drawing(account,100,"xiaoming"); you.start(); xiaoming.start(); } } //account class Account{ int money; String name; public Account(int money, String name) { this.money = money; this.name = name; } } //Bank: Simulated withdrawal class Drawing extends Thread{ Account account;//account //How much money has been withdrawn int drawingMoney; //How much money do you have now int noeMoney; public Drawing(Account account,int drawingMoney,String name){ super(); this.account=account; this.drawingMoney=drawingMoney; } @Override public void run() { if (account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"Not enough money to take"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Card Balance = Balance = Money you withdraw account.money=account.money-drawingMoney; //Money in your hand noeMoney=noeMoney+drawingMoney; System.out.println(account.name+"The balance is:"+account.money); System.out.println(this.getName()+"Money in your hand:"+noeMoney); } }
Result
The balance of the travel fund is:50 Thread-0 Money in hand: 50 The balance of the travel fund is:-50 Thread-1 Money in hand: 100
Thread Insecurity Case 3: Collection
package com.yw.syn; import java.util.ArrayList; import java.util.List; public class UnsafeList { public static void main(String[] args) { List<String> list=new ArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } System.out.println(list.size()); } }
5.2 Synchronization Method and Synchronization Block
Since we can use the private keyword to ensure that data objects can only be accessed by methods, we only need to propose a mechanism for methods, which is the synchronized keyword, which includes two uses: the synchronized method and the synchronized block.
Synchronization method: public synchronized void method(int args){}
_Synchronized methods control access to "objects". Each object corresponds to a lock. Each synchronized method must acquire a lock on the object calling the method to execute. Otherwise, the thread will block. Once the method executes, the lock will be exclusively released until the method returns. Then the blocked thread can acquire the lock and continue execution.
Defect: Declaring a large method as synchronized will affect efficiency.
_The contents that need to be modified in the method need to be locked. Too many locks waste resources.
Synchronization block: synchronized (obj){ }
_obj calls it a synchronization monitor_obj can be any object, but it is recommended that a shared resource be used as a synchronization monitor synchronization method without specifying a synchronization monitor, because the synchronization monitor for a synchronization method is this, is the object itself, or is a class
For example, modify thread insecurity case 1: Buy ticket (synchronization method)
private synchronized void buy(){ //Lock is this if (ticketNumm<=0){ flag=false; return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //Buy tickets System.out.println(Thread.currentThread().getName()+"Get it"+ticketNumm--); }
Synchronization block
Modify Thread Insecurity Case 2: Draw Money
@Override public void run() { synchronized (account){ if (account.money-drawingMoney<0){ System.out.println(Thread.currentThread().getName()+"Not enough money to take"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Card Balance = Balance = Money you withdraw account.money=account.money-drawingMoney; //Money in your hand noeMoney=noeMoney+drawingMoney; System.out.println(account.name+"The balance is:"+account.money); System.out.println(this.getName()+"Money in your hand:"+noeMoney); } }
Modify Thread Insecurity Case 3: Collection
public class UnsafeList { public static void main(String[] args) { List<String> list=new ArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } System.out.println(list.size()); } }
Synchronization Monitor Execution Procedure_1.First Thread Access, Lock Synchronization Monitor, Execute Code_2.Second Thread Access, Discover Synchronization Monitor, Can't Access_3.First Thread Access Completed, Unlock Synchronization Monitor_4.Second Thread Access, Discover Synchronization Monitor Not Locked, Lock and Access
The object of the lock is the amount of change that needs to be added or deleted
5.2.1 Supplement: Thread Security Collection CopyOnWriteArrayList
Understand first
//Collection of test thread security types public class TestJUC { public static void main(String[] args) { CopyOnWriteArrayList<String> list=new CopyOnWriteArrayList<String>(); for (int i = 0; i < 10000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
6 Deadlock
-
Threads hug the resources needed by the object and then become stuck.
-
Deadlock can occur when two or more threads are waiting for each other to release resources and execution stops. A synchronization block has locks on more than two objects at the same time.
Cases like two people putting on make-up and mirror lipstick
package com.yw.deadlock; //Deadlock: Multiple threads hold each other's needed resources and then become deadlocked public class DeadLock { public static void main(String[] args) { Makeup g1=new Makeup(0,"Grilla australis"); Makeup g2=new Makeup(1,"Snow White"); g1.start(); g2.start(); } } //Lipstick class Lipstick{ } //Mirror class Mirror{ } class Makeup extends Thread{ //Only one resource is needed, and only one is guaranteed with static static Lipstick lipstick=new Lipstick(); static Mirror mirror=new Mirror(); int choice;//Choice String girlName; //People who use cosmetics Makeup(int choice,String girlName){ this.choice=choice; this.girlName=girlName; } @Override public void run() { super.run(); } //Makeup, holding each other's locks, is to get the other's resources private void makeup() throws InterruptedException { if (choice==0){ synchronized (lipstick){ System.out.println(this.girlName+"Lock to get lipstick"); Thread.sleep(1000); synchronized (mirror){ System.out.println(this.girlName+"Get the lock on the mirror"); } } }else{ synchronized (mirror){ System.out.println(this.girlName+"Get the lock on the mirror"); Thread.sleep(2000); synchronized (lipstick){ System.out.println(this.girlName+"Lock to get lipstick"); } } } } }
As a result,
Gray Palm gets the lock for lipstick
Snow White gets the lock on the mirror
Make each other wait for the other to release resources
Solve
//Makeup, holding each other's locks, is to get the other's resources private void makeup() throws InterruptedException { if (choice==0){ synchronized (lipstick){ System.out.println(this.girlName+"Lock to get lipstick"); Thread.sleep(1000); } synchronized (mirror){ System.out.println(this.girlName+"Get the lock on the mirror"); } }else{ synchronized (mirror){ System.out.println(this.girlName+"Get the lock on the mirror"); Thread.sleep(2000); } synchronized (lipstick){ System.out.println(this.girlName+"Lock to get lipstick"); } } }
Four prerequisites for deadlock generation:1. Mutual exclusion: A resource can only be used by one process at a time. Request and Hold Conditions: A process is blocked by requests for resources and remains open to acquired resources. _3. Non-deprivation conditions: Resources already acquired by a process cannot be forcibly deprived until they have been used up. _4. Cyclic wait conditions: A head-to-tail cyclic wait resource relationship is formed between several processes.
7 Lock
Re-lockable
-
Starting with JDK 5.0, Java provides a more powerful thread synchronization mechanism -- synchronization is achieved by explicitly defining synchronization lock objects. Synchronization locks use Lock objects to act as
-
The java.util.concurrent.locks.Lock interface is a tool that controls access to shared resources by multiple threads. Locks provide exclusive access to shared resources. Only one thread can lock Lock objects at a time. A thread should obtain Lock objects before it starts accessing shared resources.
-
The ReentrantLock class implements Lock, which has the same concurrency and memory semantics as synchronized. ReentrantLock is commonly used in thread-safe control to explicitly lock and release locks.
Lock lock case
package com.yw.goji; import java.util.concurrent.locks.ReentrantLock; public class TestLock { public static void main(String[] args) { TestLock2 testLock2=new TestLock2(); new Thread(testLock2).start(); new Thread(testLock2).start(); new Thread(testLock2).start(); } } class TestLock2 implements Runnable{ int ticketNum=10; //Define lock private final ReentrantLock lock=new ReentrantLock(); @Override public void run() { while (true){ try { lock.lock();//Locking if (ticketNum>0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ticketNum--); }else{ break; } }finally { lock.unlock();//Unlock } } } }
Synchronized versus Lock_1.Lock is an explicit lock (manually open and close lock, don't forget to close lock) Synchronized is an implicit lock that automatically releases the scope_2.Lock only has code block locks, synchronized has code block locks and method locks_3.With Lock locks, the JVM will spend less time dispatching threads and perform better. (Provides more subclasses)4. Priority order: Lock > Synchronization code block (already in the method body, allocating appropriate resources) > Synchronization method (outside the method body)
8 Producer and consumer issues
-
Assuming that only one product can be stored in a warehouse, the producer puts the product into the warehouse, and the consumer takes the product out of the warehouse for consumption.
-
If there is no product in the warehouse, the producer puts the product in the warehouse, otherwise stops production and waits until the product in the warehouse is removed by the consumer.
-
If there are products in the warehouse, the consumer can take the product away from consumption, otherwise stop consumption and wait until the warehouse puts the product again.
This is a thread synchronization problem where producers and consumers share the same resource and are dependent and conditional on each other.
-
For producers, consumers should be notified to wait before they produce a product, and consumers should be notified to consume immediately after they produce a product.
-
For consumers, after consumption, to notify producers that consumption has ended, new products need to be produced for consumption.
-
In the producer-consumer problem, synchronized is not enough_synchronized to prevent concurrent updates to the same shared resource, synchronized_synchronized cannot be used to achieve message delivery (communication) between different threads
Java provides several ways to solve communication problems between threads
Note: Both methods of the Object class can only be used in synchronization methods or synchronization code blocks, otherwise lllegalMonitorStateException will be thrown
Solution 1: Concurrent Collaboration Model "Producer/Consumer Mode" - >Pipeline Method_1. Producer: Module responsible for production data (possibly method, object, thread, process); _2. Consumer: Module responsible for processing data (possibly method, object, thread, process); Buffer: Consumers cannot use producer data directly, there is a "buffer" between them
The producer puts the produced data in the buffer and the consumer pulls the data out of the buffer
8.1 Pipeline Method
package com.yw.goji; //Producer/Consumer Model"- >Procedure Law //Producer Consumer Product Buffer public class TestPC { public static void main(String[] args) { SynContainer container=new SynContainer(); Productor productor=new Productor(container); Comsumer comsumer=new Comsumer(container); productor.start(); comsumer.start(); } } //Producer class Productor extends Thread{ SynContainer container; public Productor(SynContainer container){ this.container=container; } //production @Override public void run() { for (int i = 0; i <100 ; i++) { container.push(new Chicken(i)); System.out.println("Produced"+i+"Chicken"); } } } //Consumer class Comsumer extends Thread{ SynContainer container; public Comsumer(SynContainer container){ this.container=container; } //consumption @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Consumed-->"+container.pop().id+"Chicken"); } } } //product class Chicken{ int id;//Product Number public Chicken(int id) { this.id = id; } } //Buffer class SynContainer{ //Container size Chicken[] chickens=new Chicken[10]; //Container Counter int count=0; //Producer put in product public synchronized void push(Chicken chicken){ if (count==chickens.length){ //Notify consumers of consumption, producers wait try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //If it's not full, we need to throw it in chickens[count]=chicken; count++; //Consumers can be notified of their consumption this.notifyAll(); } //Consumers put in products public synchronized Chicken pop(){ //Judging whether to consume if (count==0){ //Waiting for producers to produce, consumers to wait try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //If consumable count--; Chicken chicken=chickens[count]; //Consumption is over, notify producer of production this.notifyAll(); return chicken; } }
Solution 2:
Concurrent Collaboration Model "Producer/Consumer Mode" - > Semaphore Method
8.2 semaphore method
package com.yw.goji; //Producer/Consumer Mode"- > Signal Light Method, Signpost Resolution public class TestPC2 { public static void main(String[] args) { TV tv=new TV(); new PLayer(tv).start(); new Watcher(tv).start(); } } //Producer--Actor class PLayer extends Thread{ TV tv; public PLayer(TV tv){ this.tv=tv; } @Override public void run() { for (int i = 0; i < 20; i++) { if (i%2==0){ this.tv.play("Happy Camp"); }else { this.tv.play("Tremolo: Record the good life"); } } } } //Consumer--"Audience class Watcher extends Thread{ TV tv; public Watcher(TV tv){ this.tv=tv; } @Override public void run() { for (int i = 0; i < 20; i++) { this.tv.watch(); } } } //Product--"Program class TV{ //Performers perform, audiences wait //Audience watching, actor waiting String voice;//Performing Programs boolean flag=true; //perform public synchronized void play(String voice){ if (!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("The actors performed:"+voice); //Notify viewers to watch this.voice=voice; //Notification Wake-up this.notifyAll(); this.flag=!this.flag; } //watch public synchronized void watch(){ if (flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Watched:"+voice); //Inform an actor to perform this.notifyAll(); } }
9 Thread Pool
Background: Often created and destroyed resources that are particularly heavily utilized, such as threads in concurrent situations, can have a significant impact on performance.
Idea: Create many threads in advance, put them in the thread pool, get them directly when using, and put them back into the pool when using them. Frequent creation of destruction and reuse can be avoided. Similar to public transportation in life.
Benefits: 1. Increase response speed (reduce the time to create new threads)2. Reduce resource consumption (reuse threads in the thread pool, do not need to be created every time)3. Easy thread management (...) corePoolSize: Core pool size_maximumPoolSize: Maximum threads
JDK 5.0 has provided thread pool related API s:_ExecutorService and Executors ExecutorService: true thread pool interface. Common subclasses ThreadPoolExecutor_void execute(Runnable cgmmand): perform tasks/commands with no return value and are generally used to execute Runnable_Future submit (Callable) : Execute tasks, have return values, and generally perform Callable_void shutdown(): Close connection pools_Executors:Tool classes, Thread pools'factory classes, which are used to create and return different types of thread pools
package com.yw.goji; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //Test Thread Pool public class TestPool { public static void main(String[] args) { //1 Create a thread pool //The newFixedThreadPool parameter is: Thread pool size ExecutorService service= Executors.newFixedThreadPool(10); //implement service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); //Close Connection service.shutdown(); } } class MyThread implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()); } }