Multithreading
Thread introduction
-
Program: an ordered collection of instructions and data, which is only a static concept.
-
Process is an execution process of executing program. As a dynamic concept, it is the unit of system resource allocation.
-
A process can contain multiple threads and have at least one thread
-
Real multithreading means that there are multiple CPUs, i.e. multiple cores, such as servers. If the simulated multithreading is essentially in the same cpu, it can only execute one code task in the same time unit, not at the same time. It is just the illusion of fast switching.
-
Threads are independent execution paths.
-
Multithreading is developed in the process, and the thread operation is scheduled by the scheduler without human intervention.
-
Concurrency control needs to be added to solve the problem of resource grabbing.
Inherit Thread class
package Thread.lesson1; //Method 1 for creating a Thread: inherit the Thread class, rewrite the run method, and call start to start the Thread //Note: thread startup is not necessarily executed immediately and is scheduled by cpu public class Dom1 extends Thread{ @Override public void run(){ //run method thread body for (int i = 0 ; i < 20 ; i ++) { System.out.println("Threadstudy"+i); } } public static void main(String[] args) { //Main thread main thread //Create a thread object Dom1 dom1 = new Dom1(); //Calling the run method will only be executed in sequence, while the start method can be scheduled by the cpu to interact with multiple threads at the same time //dom1.run(); //Call the start method to start the thread, dom1.start(); //Write a test to see the effect for (int i = 0 ; i < 1000 ; i ++){ System.out.println("Thread------" + i); } } }
Network diagram Download
import java.net.URL; public class dom1 extends Thread { private String url; private String name; //constructor public dom1(String url,String name){ this.url = url; this.name = name; } //The execution body of the download image thread @Override public void run() { webDown webdown = new webDown(); try { webdown.down(url,name); } catch (IOException e) { e.printStackTrace(); } System.out.println("Downloaded file named" + name); } public static void main(String[] args) { //My head dom1 t1 = new dom1("http://i2.hdslb.com/bfs/face/536ff5e823cb3c354a71880edb3a15c826d5634d.jpg", "536ff5e823cb3c354a71880edb3a15c826d5634d.jpg"); //Mad god head dom1 t2 = new dom1("http://i2.hdslb.com/bfs/face/83bb511365da513c55aa3d1958524f3b7db40684.jpg", "83bb511365da513c55aa3d1958524f3b7db40684.jpg"); //Head of director dom1 t3 = new dom1("http://i1.hdslb.com/bfs/face/f85fbedb0a6bfebedba167791a816e1b36f757d9.jpg", "f85fbedb0a6bfebedba167791a816e1b36f757d9.jpg"); //Execution thread t1.start(); t2.start(); t3.start(); } } //Downloader class webDown{ public void down(String url,String name) throws IOException { //File tool class: FileUtils try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO Abnormal, down There is something wrong with the method"); } } }
The download results are not executed from top to bottom. The reason is the same as above.
Implement Runnable interface
- Compared with the Thread class, Runnable is more recommended and avoids the limitations of single inheritance. However, Runnable is flexible and can enable an object to be used by multiple threads.
Use Runnable to modify the above two examples
//Create thread method 2: implement the runnable interface and rewrite the run method. The execution thread needs to drop into the runnable interface implementation class and call the start method public class dom2 implements Runnable{ @Override //run method thread body public void run() { for (int i = 0; i < 20 ; i++){ System.out.println("Look at the code" +i); } } public static void main(String[] args) { //Create an implementation object of the Runnable interface dom2 dom2 = new dom2(); //Create a thread object and start the thread proxy through the thread object //Thread thread = new Thread(); //thread.start(); // Equivalent to the above two sentences, abbreviated as: new Thread(dom2).start(); for (int i = 0; i < 1000 ; i++){ System.out.println("study" +i); } } }
import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; public class dom1 implements Runnable { private String url; private String name; //constructor public dom1(String url,String name){ this.url = url; this.name = name; } //The execution body of the download image thread @Override public void run() { webDown webdown = new webDown(); try { webdown.down(url,name); } catch (IOException e) { e.printStackTrace(); } System.out.println("Downloaded file named" + name); } public static void main(String[] args) { //My head dom1 t1 = new dom1("http://i2.hdslb.com/bfs/face/536ff5e823cb3c354a71880edb3a15c826d5634d.jpg", "536ff5e823cb3c354a71880edb3a15c826d5634d.jpg"); //Mad god head dom1 t2 = new dom1("http://i2.hdslb.com/bfs/face/83bb511365da513c55aa3d1958524f3b7db40684.jpg", "83bb511365da513c55aa3d1958524f3b7db40684.jpg"); //Head of director dom1 t3 = new dom1("http://i1.hdslb.com/bfs/face/f85fbedb0a6bfebedba167791a816e1b36f757d9.jpg", "f85fbedb0a6bfebedba167791a816e1b36f757d9.jpg"); //Execution thread new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); } } //Downloader class webDown{ public void down(String url,String name) throws IOException { //File tool class: FileUtils try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO Abnormal, down There is something wrong with the method"); } } }
Understanding concurrency problems
//Multiple threads operate on an object at the same time //Example of buying a train ticket //Problems are found after execution. When multiple threads execute the same resource, the thread is unsafe and the data is disordered. Concurrency problem public class dom3 implements Runnable{ @Override public void run() { while (true){ if(Nums <= 0){ break; } try { //Analog delay, delay 0.2s Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //Thread.currentThread().getName(): current thread name System.out.println(Thread.currentThread().getName()+"Got the second" +Nums--+"ticket"); } } //Number of votes private int Nums = 10; public static void main(String[] args) { dom3 dom3 = new dom3(); //You can name each thread new Thread(dom3,"Two dogs").start(); new Thread(dom3,"Lao Liu").start(); new Thread(dom3,"cattle").start(); } }
Tortoise and rabbit race
//Simulated tortoise rabbit race (classic written test questions) //Define a track distance, getting closer and closer to the finish line //Judge whether the game is over //Print out the winner //The game begins //The rabbit has to sleep //Bastard won public class dom4 implements Runnable{ @Override public void run() { for (int i = 0; i <= 100; i++) { //Let the rabbit sleep. Sleep for a while every ten steps. Sleep for 0.01s is enough. You can't sleep at the beginning if(Thread.currentThread().getName().equals("rabbit")&& i%10==0 &&i!=0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } //Judge whether the game is over boolean flag = gameOver(i); //The game is over if(flag){ break; } System.out.println(Thread.currentThread().getName()+"-->Run away"+ i + "step"); } } //Winner - static private static String Winner; //Judge whether to complete the game private boolean gameOver(int stops) { if (Winner != null) { //Winner already exists return true; } { if (stops >= 100) { Winner = Thread.currentThread().getName(); System.out.println("winner is" + Winner); return true; } } return false; } public static void main(String[] args) { dom4 dom4 = new dom4(); new Thread(dom4,"rabbit").start(); new Thread(dom4,"tortoise").start(); } }
Implement Callable interface*
import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; //Thread creation method 3: Callable interface //You can define the return value and throw an exception public class dom5 implements Callable<Boolean> { private String url; private String name; //constructor public dom5(String url,String name){ this.url = url; this.name = name; } //The execution body of the download image thread @Override public Boolean call() { webDown webdown = new webDown(); try { webdown.down(url,name); } catch (IOException e) { e.printStackTrace(); } System.out.println("Downloaded file named" + name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { //My head dom5 t1 = new dom5("http://i2.hdslb.com/bfs/face/536ff5e823cb3c354a71880edb3a15c826d5634d.jpg", "536ff5e823cb3c354a71880edb3a15c826d5634d.jpg"); //Mad god head dom5 t2 = new dom5("http://i2.hdslb.com/bfs/face/83bb511365da513c55aa3d1958524f3b7db40684.jpg", "83bb511365da513c55aa3d1958524f3b7db40684.jpg"); //Head of director dom5 t3 = new dom5("http://i1.hdslb.com/bfs/face/f85fbedb0a6bfebedba167791a816e1b36f757d9.jpg", "f85fbedb0a6bfebedba167791a816e1b36f757d9.jpg"); //Create execution service: ExecutorService ser = Executors.newFixedThreadPool(3); //Submit for 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 service ser.shutdown(); } } //Downloader class webDown{ public void down(String url,String name) throws IOException { //File tool class: FileUtils try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); System.out.println("IO Abnormal, down There is something wrong with the method"); } } }
Static proxy
//Surrogate marriage //Proxy mode: both real objects and proxy objects should implement the same interface //The proxy object should represent the real role. The proxy object can do things that the proxy object can't do. The real object focuses on doing its own things //The bottom implementation idea of thread public class dom6 { public static void main(String[] args) { //WeddingCompany weddingCompany = new WeddingCompany(new You()); //weddingCompany.HappyMarry(); new WeddingCompany(new You()).HappyMarry();//Lite } } //interface: interface interface Marry{ void HappyMarry(); } //Real role class You implements Marry{ @Override public void HappyMarry() { System.out.println("I'm married"); } } //delegable role class WeddingCompany implements Marry{ //Agent - real target role private Marry target; public WeddingCompany(Marry target){ this.target = target; } @Override public void HappyMarry() { after(); this.target.HappyMarry(); before(); } private void after(){ System.out.println("Decorate the venue"); } private void before(){ System.out.println("Closing payment"); } }
Lamda expression
Abbreviated code
/* Derivation of lamda expression */ public class dom7 { //Static inner class static class lamda2 implements Lamda{ @Override public void lamDa() { System.out.println("i like lamda2"); } } public static void main(String[] args) { Lamda la = new Lam(); la.lamDa(); la = new lamda2(); la.lamDa(); //Local inner class class lamda3 implements Lamda{ @Override public void lamDa() { System.out.println("i like lamda3"); } } la = new lamda3(); la.lamDa(); //Anonymous inner class. There is no class name. You must use the interface or parent class la = new Lamda() { @Override public void lamDa() { System.out.println("i like lamda4"); } }; la.lamDa(); //Simplify with Lamda //lamda simplifies step by step, simplifying parameter types, parentheses and curly braces //lamda expressions can only be reduced to one line when there is only one line. Multiple lines need to be {} wrapped //Must be a functional interface (interface has only one method) //The parameter type can also be removed from multiple parameters, and all parameters to be removed; la = () ->{ System.out.println("i like lamda5"); }; la.lamDa(); la = () ->System.out.println("i like lamda6"); la.lamDa(); } } //Define a functional interface interface Lamda{ void lamDa(); } //Implementation class class Lam implements Lamda{ @Override public void lamDa() { System.out.println("i like lamda"); } }
Thread stop
- Five thread states:
-
- Creation status: new, that is, new status
- Ready state: enter after calling the start () method
-
- Blocking state: call sleep or lock state in operation, end of state and readiness again.
- Running state: actually executing thread body code block
- Dead state: thread interrupt or end
//It is recommended that the thread stop itself //Dead circulation or stop is not recommended, that is, the party fee that jdk does not recommend is forcibly stopped public class dom8 implements Runnable{ //Set a flag bit private boolean flag = true; @Override public void run() { int i = 0; while (flag){ System.out.println("run---Thread"+i); i++; } } //Set a public method to stop the thread and change the flag bit public void stop(){ this.flag= false; } public static void main(String[] args) { dom8 dom8 = new dom8(); new Thread(dom8).start(); for (int i = 0; i < 1000; i++) { System.out.println("main"+i); if(i == 900){ //Call the stop method to switch Peugeot and stop the thread dom8.stop(); System.out.println("run The thread should stop"); } } } }
Thread sleep
- sleep: Unit - milliseconds (1s = 1000ms);
- An exception needs to be thrown
- Each object has a lock, and sleep will not release the lock*
//Simulate the network delay, amplify the occurrence of the problem, and return to the above ticket purchase problem public class dom9 implements Runnable{ @Override public void run() { while (true){ if(Nums <= 0){ break; } try { //Analog delay, delay 0.2s Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //Thread.currentThread().getName(): current thread name System.out.println(Thread.currentThread().getName()+"Got the second" +Nums--+"ticket"); } } //Number of votes private int Nums = 10; public static void main(String[] args) { dom3 dom3 = new dom3(); //You can name each thread new Thread(dom3,"Two dogs").start(); new Thread(dom3,"Lao Liu").start(); new Thread(dom3,"cattle").start(); } }
import java.text.SimpleDateFormat; import java.util.Date; //Analog countdown public class dom9{ public static void main(String[] args) { //count down // try { // TimeDown(); // } catch (InterruptedException e) { // e.printStackTrace(); // } //Print current time Date date = new Date(System.currentTimeMillis());//Get the current system time while (true){ try { Thread.sleep(1000); System.out.println(new SimpleDateFormat("HH:mm:ss").format(date)); date = new Date(System.currentTimeMillis());//Update time } catch (InterruptedException e) { e.printStackTrace(); } } } public static void TimeDown() throws InterruptedException { int time = 10; while (true) { Thread.sleep(100); System.out.println(time--); if (time<=0){ break; } } } }
Thread yield
//Change the process from running state to ready state without blocking //Comity does not necessarily succeed. It depends on your mood public class dom10 { 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();//Comity System.out.println(Thread.currentThread().getName()+"Thread stop execution"); } }
Thread enforcement - join
//The join method can be understood as forcibly jumping in the queue, blocking other processes and being overbearing! public class dom11 implements Runnable{ @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("vip coming"+i); } } public static void main(String[] args) { //Start thread dom11 dom11 = new dom11(); Thread thread = new Thread(dom11); thread.start(); //Main thread for (int i = 0; i < 500; i++) { if (i == 200){ try { thread.join();//Jump the queue, let the current thread step aside first, and so on. Let other threads go first } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("main"+i); } } }
Observe thread state - state
//Observe the status of the test thread public class dom12 { public static void main(String[] args) { Thread thread = new Thread(()->{ //The thread starts for five seconds for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("`````"); }); //Observation state Thread.State state = thread.getState(); System.out.println(state); //NEW //Observe after startup thread.start(); state = thread.getState(); System.out.println(state); //RUNNABLE while (state!=Thread.State.TERMINATED){//The thread does not terminate and is always in the output state try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } state = thread.getState();//Update thread status System.out.println(state);//Output status } } }
Priority of thread - priority
//Test thread priority //Priority range 1-10; If the range is exceeded, an error will be reported. The higher the priority, the more resources the cpu gives, which is not absolute! public class dom13 { public static void main(String[] args) { //Main thread default priority - 5 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); Thread t7 = new Thread(myPriority); Thread t8 = new Thread(myPriority); //Set the priority before starting! t1.start(); t2.setPriority(1); t2.start(); t3.setPriority(6); t3.start(); t4.setPriority(Thread.MAX_PRIORITY); t4.start(); t5.setPriority(Thread.NORM_PRIORITY); t5.start(); } } class MyPriority implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+"____"+Thread.currentThread().getPriority()); } }
daemon thread
//Test: protect you all your life //Life is only 36500 days //The program will not wait for the execution of the daemon thread. The program must ensure that the execution of the user thread is completed, that is, the daemon thread is still protected until the end of the process. public class dom14 { public static void main(String[] args) { dom dom = new dom(); You2 you2 = new You2(); Thread thread = new Thread(dom); thread.setDaemon(true);//The default is flash. All normal threads are user threads thread.start();//Daemon thread start new Thread(you2).start(); } } class dom implements Runnable{ @Override public void run() { while (true){ System.out.println("Guard you"); } } } class You2 implements Runnable{ @Override public void run() { for (int i = 0; i < 36500; i++) { System.out.println("You should live a happy life all your life"); } System.out.println("---goodBye! word---"); } }
Thread synchronization mechanism
-
Queues and locks
-
Safety = = reduced performance (you can't have both fish and bear's paw)
Three unsafe cases
//Unsafe ticket buying //Threads are unsafe and have negative numbers -- each thread has its own independent workspace and does not affect each other in its own memory. public class dom15{ public static void main(String[] args) { BuyTicket buyTicket1 = new BuyTicket(); new Thread(buyTicket1,"Zhao").start(); new Thread(buyTicket1,"money").start(); new Thread(buyTicket1,"Sun").start(); new Thread(buyTicket1,"Lee").start(); } } //Ticket buying method class BuyTicket implements Runnable{ private int Nums = 10; private boolean flag = true; @Override public void run() { while (flag){ buy(); } } private void buy(){ if(Nums<=0){ return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"Got it"+Nums--); } }
//Unsafe withdrawal //Two people withdraw money together public class dom16 { public static void main(String[] args) { Account account = new Account(100,"fund"); back you = new back(account,50,"you"); back her = new back(account,100,"she"); you.start(); her.start(); } } //account class Account{ int money; String name; public Account(int money,String name) { this.money = money; this.name = name; } } //Bank: simulated withdrawal class back extends Thread{ //account Account account ; //How much is it now int nowMoney; //How much is it int DrawingMoney; public back(Account account,int DrawingMoney,String name) { super(name); this.account = account; this.DrawingMoney = DrawingMoney; } public void run(){ //Judge whether the money is enough if(account.money-DrawingMoney < 0){ System.out.println(Thread.currentThread().getName()+"The money is not enough"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } account.money = account.money - DrawingMoney ; nowMoney = nowMoney + DrawingMoney; System.out.println(this.getName()+"--Now there are--"+ nowMoney); System.out.println(account.name+"The balance is"+account.money); } }
import java.util.ArrayList; import java.util.List; //Thread unsafe collection, it is difficult to achieve the goal of creating all 1000 threads //Note that the system can create a limited number of threads public class dom17 { public static void main(String[] args) { List<String> list = new ArrayList<String>() ; for(int i = 0;i< 1000;i++) { new Thread(()->list.add(Thread.currentThread().getName())).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
Synchronization method and synchronization block synchronized
Optimize and modify the above three unsafe cases - lock
//Unsafe ticket buying //Thread unsafe, negative number public class dom15{ public static void main(String[] args) { BuyTicket buyTicket1 = new BuyTicket(); new Thread(buyTicket1,"Zhao").start(); new Thread(buyTicket1,"money").start(); new Thread(buyTicket1,"Sun").start(); new Thread(buyTicket1,"Lee").start(); } } //Ticket buying method class BuyTicket implements Runnable{ private int Nums = 10; private boolean flag = true; @Override public void run() { while (flag){ buy(); } } //The synchronized synchronization method locks this to ensure thread safety private synchronized void buy(){ if(Nums<=0){ return; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"Got it"+Nums--); } }
//Unsafe withdrawal //Two people withdraw money together public class dom16 { public static void main(String[] args) { Account account = new Account(100,"fund"); back you = new back(account,50,"you"); back her = new back(account,100,"she"); you.start(); her.start(); } } //account class Account{ int money; String name; public Account(int money,String name) { this.money = money; this.name = name; } } //Bank: simulated withdrawal class back extends Thread{ //account Account account ; //How much is it now int nowMoney; //How much is it int DrawingMoney; public back(Account account,int DrawingMoney,String name) { super(name); this.account = account; this.DrawingMoney = DrawingMoney; } public void run(){ //Synchronization block //The key lies in the object of the lock. The object of the lock must be the amount of change. If the bank cannot be locked, the bank card must be locked synchronized (account){ //Judge whether the money is enough if(account.money-DrawingMoney < 0){ System.out.println(Thread.currentThread().getName()+"The money is not enough"); return; } try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } account.money = account.money - DrawingMoney ; nowMoney = nowMoney + DrawingMoney; System.out.println(this.getName()+"--Now there are--"+ nowMoney); System.out.println(account.name+"The balance is"+account.money); } } }
import java.util.ArrayList; import java.util.List; //Thread unsafe collection, it is difficult to achieve the goal of creating all 1000 threads //Note that the system can create a limited number of threads public class dom17 { public static void main(String[] args) { List<String> list = new ArrayList<String>() ; for(int i = 0;i< 1000;i++) { new Thread(()->{ synchronized (list){ list.add(Thread.currentThread().getName()); } }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
CopyOnWriteArrayList
- Collection of security types
import java.util.concurrent.CopyOnWriteArrayList; //A collection of test juc security types public class dom18 { public static void main(String[] args) { //And contract CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>(); for (int i = 0; i < 1000; i++) { new Thread(()->{ list.add(Thread.currentThread().getName()); }).start(); } try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(list.size()); } }
deadlock
- Two threads are waiting for each other to release resources and are deadlocked with each other
- When a synchronization block has more than two locks, it is prone to the problem of life and death lock
//Deadlock problem public class dom19 { public static void main(String[] args) { new Thread(new MakeUp(1,"Cuihua")).start(); new Thread(new MakeUp(0,"Hemp flowers")).start(); } } //Lipstick class Lipstick{} //mirror class Mirror{} class MakeUp extends Thread{ //There is only one resource static Lipstick lipstick = new Lipstick(); static Mirror mirror = new Mirror(); //selector int choise; //role String name; MakeUp(int choise,String name){ this.choise = choise; this.name = name; } @Override public void run() { makeup(); } //Make up and hold each other's locks private void makeup(){ if(choise == 0){ //Lock current resource synchronized (lipstick){ System.out.println(this.name + "Get lipstick"); try { //Get another resource in a second Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (mirror){ System.out.println(this.name+"Get the mirror"); } } }else { synchronized (mirror){ System.out.println(this.name + "Get the mirror"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lipstick){ System.out.println(this.name+"Get lipstick"); } } } } }
- In the above example, two objects occupy each other's required resources and are waiting to release resources. A deadlock problem occurs. Take out the "lock in lock" to solve the problem.
//Make up and hold each other's locks private void makeup(){ if(choise == 0){ //Lock current resource synchronized (lipstick){ System.out.println(this.name + "Get lipstick"); try { //Get another resource in a second Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (mirror){ System.out.println(this.name+"Get the mirror"); } }else { synchronized (mirror){ System.out.println(this.name + "Get the mirror"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized (lipstick){ System.out.println(this.name+"Get lipstick"); } } }
Lock lock
-
Lock: explicit lock. Manual switch is required
synchronized: an implicit lock that is automatically released out of the scope
-
lock: only code block locks, no method locks
-
Lock lock has better performance and better expansibility
import java.util.concurrent.locks.ReentrantLock; //Lock lock public class dom20 { public static void main(String[] args) { Ticket ticket = new Ticket(); new Thread(ticket,"Lao Zhang").start(); new Thread(ticket,"Two dogs").start(); new Thread(ticket,"Three guns").start(); } } class Ticket implements Runnable{ int Num = 10; //Define lock lock private final ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true){ try { lock.lock();//Lock if(Num>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"--Got the second"+ Num-- +"Ticket"); }else { break; } }finally { lock.unlock();//Release lock } } } }
Producer consumer issues*
Pipe program method
//Producer consumer model - using buffer to solve: pipe process method //Producer, consumer, product, buffer public class dom21 { public static void main(String[] args) { SyContainer syContainer = new SyContainer(); new Productor(syContainer).start(); new Consumer(syContainer).start(); } } //producer class Productor extends Thread{ SyContainer container; public Productor(SyContainer 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 Consumer extends Thread{ SyContainer container; public Consumer(SyContainer container){ this.container = container; } //consumption @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("Consumption" + container.pop().id + "Chicken"); } } } //product class Chicken { //Product number int id; public Chicken(int id){ this.id = id; } } //buffer class SyContainer{ //Container size Chicken[] chickens = new Chicken[10]; //Capacity counter int str = 0; //Producers throw in products public synchronized void push(Chicken chicken){ //Full, production stop if(str == chickens.length){ //Inform consumers to consume and producers to wait try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //Not full, production chickens[str] = chicken; str++; //Inform consumers of consumption this.notifyAll(); } //Consumer products public synchronized Chicken pop(){ //Judge whether it can be consumed if(str==0){ //wait try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //Can consume str--; Chicken chicken = chickens[str]; //Notify the producer of production after consumption this.notifyAll(); return chicken; } }
Signal lamp method
//Signal lamp method - solve through flag bit - flag public class dom22 { public static void main(String[] args) { Tv tv = new Tv(); new player(tv).start(); new watcher(tv).start(); } } //producer 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("Tom and Jerry"); }else { this.tv.play("Shaking tiktok records good life"); } } } } //consumer class watcher extends Thread{ Tv tv; public watcher(Tv tv){ this.tv = tv; } @Override public void run() { for (int i = 0; i < 20; i++) { tv.watch(); } } } //Products - programs class Tv{ //Actors perform and the audience wait; The audience watched and the actors waited String voice; boolean flag = true; //perform public synchronized void play(String voice){ if(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Performed:" +voice); this.notifyAll();//Notification, wake up this.voice = voice; 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 the actors to perform this.notifyAll(); this.flag = !this.flag; } }
Thread pool
- Refer to the callable interface
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //Side thread pool public class dom23 { public static void main(String[] args) { //Create thread pool ExecutorService service = Executors.newFixedThreadPool(10);//Thread pool size 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()); } }