Thread and process concepts:
- Process:
- Process is the basic unit of resource (CPU, memory, etc.) allocation. It is an instance of program execution.
- When the program runs, the system will create a process, allocate resources for it, and then put the process into the process ready queue
- When the process scheduler selects it, it will allocate CPU time for it and the program will start to run.
- Thread:
- Thread is the smallest unit of program execution. It is an execution flow of a process and the basic unit of CPU scheduling and dispatching.
- A process can be composed of many threads. All resources of the process are shared among threads. Each thread has its own stack and local variables.
- Threads are independently scheduled and executed by the CPU. In a multi CPU environment, multiple threads are allowed to run at the same time. Similarly, multithreading can also realize concurrent operation, and each request is allocated a thread to process.
Concurrency and parallelism
-
Concurrency: at the same time, multiple tasks are executed alternately, resulting in the illusion of "seemingly simultaneous". The process of single core CPU executing multiple tasks is called concurrency
-
Parallel: at the same time, multiple tasks are executed at the same time, and multi-core CPU s are executed at the same time to realize parallel
Basic use of threads:
Two ways to create threads
- Inherit the Thread class, rerun the run method, extend Thread, and override the run method
- Implement the Runable interface, re run the method implements Runnable, and rewrite the run method
Example: start a thread console and print "xxxx" once a second
package Com.JW.Demo.xiancheng; public class Demo { public static void main(String[] args) { Dog dog = new Dog(); dog.start(); } } class Dog extends Thread { @Override public void run() { while (true) { System.out.println(Thread.currentThread().getName() + "Woof, woof !!!"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
- Why do you call the start method instead of directly calling the run() method when starting a process
Example: thread application - implement Runnable interface
explain:
java is single inheritance. In some cases, a class may have inherited a parent class. At this time, it is obviously impossible to create a Thread by inheriting the Thread class method.
Static proxy class, thread
public class Demo5 { public static void main(String[] args) { Dog dog = new Dog(); //runnable is implemented ThreadProxy porxy = new ThreadProxy(dog); porxy.start(); // Thread thread = new Thread(dog); // thread.start(); } } // Thread agent class simulates a minimalist thread class class ThreadProxy implements Runnable { // You can treat the Proxy class as ThreadProxy // Type Runnable private Runnable target = null;; @Override public void run() { // TODO Auto-generated method stub if (target != null) { target.run(); // Dynamic binding (run type target object) } } public ThreadProxy(Runnable run) { this.target = run; } public void start() { start0(); } public void start0() { run(); } } class Dog implements Runnable { int count = 0; @Override public void run() { while (true) { System.out.println("run is laoding..." + (++count) + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (count == 8) { break; } } } }
The thread can be developed by implementing the Runnable interface method, but the main method cannot be started by using the start() method. It can only be started by opening a new thread
Inherit the difference between Thread Vs and Runnable
-
From the design of java, there is no difference in creating threads by inheriting threads or implementing the Runable interface. From the jdk help document, we can see that the Thread class itself implements the Runnable interface, start() - > start0()
-
The implementation of runnable interface is more suitable for multiple threads sharing a resource, and avoids the limitation of single inheritance
Thread thread class method
Common thread methods
- setName sets the thread name
- getName gets the name of the thread
- Start executes the thread, and the bottom layer of the java virtual machine calls the start0 method of the thread
- Run calls the run method of the thread object
- setPriority changes the priority of a thread
- getPriority gets the priority of the thread
package Com.JW.Demo; /** * Thread termination * @author think * */ public class Demo7 { public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); System.out.println("main Thread start"); Thread.sleep(5000); t.setFlag(false); Thread thread = new Thread(); } } class T extends Thread{ private boolean flag = true; int num = 0; @Override public void run() { while(flag) { try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"Thread start"+(++num)); } } void setFlag(boolean flag) { this.flag = flag; } }
- sleep sleeps the currently executing thread for a specified number of milliseconds
- Interrupt interrupt thread - yield the comity of the thread, give up the CPU and let other threads execute, but the comity time is uncertain, so it may not succeed.
package Com.JW.Demo; /** * Thread interrupt * * @author think * */ public class Demo8 { public static void main(String[] args) throws InterruptedException { Denfind denfind = new Denfind(); denfind.setName("lao wang "); denfind.setPriority(Thread.MIN_PRIORITY); denfind.start(); // Interrupt sleep of subroutine for (int i = 0; i < 5; i++) { Thread.sleep(1000); System.out.println("test => "+i); } denfind.interrupt(); } } class Denfind extends Thread { int count = 0; @Override public void run() { while (true) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + "move" + (++count) + "Something"); } try { System.out.println(Thread.currentThread().getName()+"Dormant..."); Thread.sleep(20000); } catch (InterruptedException e) { // TODO Auto-generated catch block System.out.println(Thread.currentThread().getName()+"Was interrupted"); e.printStackTrace(); } } } }
- join: thread queue jumping. Once the queue jumping thread is successful, it is specified to complete all tasks in the inserted thread first
package Com.JW.Demo; /** * Thread insertion * @author think * */ public class Demo9 { public static void main(String[] args) throws InterruptedException { Thread_Eat eat = new Thread_Eat(); eat.start(); for (int i = 0; i < 20; i++) { Thread.sleep(1000); System.out.println("main The thread is dry" + i); if(i == 5) { System.out.println("Let the child thread execute the task"); eat.join(); // It is equivalent to letting the child thread execute first } } } } class Thread_Eat extends Thread{ @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"The thread is dry" + i); } } }
Case: create a sub thread, output hello every 1s, output 20 times, and the main thread outputs hi every 1s, output 20 times. It is required that two threads execute at the same time. After the main thread outputs 5 times, let the sub thread run and the main thread continue
package Com.JW.Demo; /** * Thread insertion * @author think * */ public class Demo9 { public static void main(String[] args) throws InterruptedException { Thread_Eat eat = new Thread_Eat(); eat.start(); for (int i = 0; i < 20; i++) { Thread.sleep(1000); System.out.println("main thread hi" + i); if(i == 5) { System.out.println("Let the child thread execute the task"); eat.join(); // It is equivalent to letting the child thread execute first } } } } class Thread_Eat extends Thread{ @Override public void run() { for (int i = 0; i < 10; i++) { try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"thread hello" + i); } } }
Pay attention to the details
- The bottom layer of start will create a new thread. Calling run is a simple method call and will not start a new thread
- Range of thread priorities
- Interrupt interrupts a thread, but does not really end a thread, so it is generally used to interrupt a dormant thread
- The static method of sleep thread to make the current thread sleep
Ticket issue
Note: solve the problem of oversold votes
Use Thread to simulate ticketing problems
package Com.JW.Demo; import org.junit.Test; /** * Ticket selling thread control * @author think * */ public class Demo6 { public static void main(String[] args) { System.out.println("First operation"); Ticket ticket = new Ticket(); // Ticket ticket1 = new Ticket(); // Ticket ticket2 = new Ticket(); // // ticket.start(); // ticket1.start(); // ticket2.start(); Thread thread = new Thread(ticket); Thread thread1 = new Thread(ticket); Thread thread2 = new Thread(ticket); thread.start(); thread1.start(); thread2.start(); } @Test public void test() { int b = 1; b=b++; int a = 1; a=++a; // ++After that, assign values first and then add operations // ++Self incrementing assignment before System.out.println("a="+a+"b="+b); } } class Ticket extends Thread{ int ticketNum = 100; @Override public void run() { while(true) { if(ticketNum <= 0) { System.out.println("The tickets have been sold out!!!"); break; } try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"One ticket sold at the window, the rest"+(ticketNum--)); } } }
It can be seen that this scheme is flawed
Simulate ticket selling using Runnable interface
package Com.JW.Demo.xiancheng; public class Run_ticket { public static void main(String[] args) { Ticket_method1 ticket_method1 = new Ticket_method1(); Thread thread = new Thread(ticket_method1); Thread thread1 = new Thread(ticket_method1); Thread thread2 = new Thread(ticket_method1); thread.start(); thread1.start(); thread2.start(); } } class Ticket_method1 implements Runnable{ int ticketNum = 100; @Override public void run() { while(true) { if(ticketNum <= 0) { System.out.println("The tickets have been sold out!!!"); break; } try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"One ticket sold at the window, the rest"+(ticketNum--)); } } }
Solution: lock
package Com.JW.Demo; /** * Lock the thread * * @author think * */ public class Demo11 { public static void main(String[] args) { sell_ticket ticket = new sell_ticket(); // sell_ticket ticket1 = new sell_ticket(); // sell_ticket ticket2 = new sell_ticket(); // // ticket.start(); // ticket1.start(); // ticket2.start(); Thread thread = new Thread(ticket); Thread thread1 = new Thread(ticket); Thread thread2 = new Thread(ticket); thread.start(); thread1.start(); thread2.start(); } } class sell_ticket extends Thread { int ticketNum = 50; @Override public void run() { synchronized (this) { while (true) { if (ticketNum <= 0) { System.out.println("The tickets have been sold out!!!"); break; } try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "One ticket sold at the window, the rest" + (ticketNum--)); } } } }
Usage of daemon thread:
User thread and daemon thread
- User thread: also known as worker thread, when the task execution of the thread is completed or the notification method ends
- Daemon thread: it generally serves the worker thread. When all user threads end, the daemon thread ends automatically
- Common daemon threads: garbage collection mechanism
package Com.JW.Demo.xiancheng; /** * Daemon * @author think * */ public class Demo3 { public static void main(String[] args) throws InterruptedException { MyDeamoThread thread = new MyDeamoThread(); thread.setDaemon(true); thread.start(); for (int i = 0; i < 10; i++) { System.out.println("main start to loading..."); Thread.sleep(1000); } } } class MyDeamoThread extends Thread{ @Override public void run() { for(;;) { try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("xx - xx method "); } } }
main start to loading... xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method main start to loading... xx - xx method xx - xx method xx - xx method xx - xx method
Daemon thread: monitor the information of other threads and obtain information, so that when a thread ends, other threads also end
Thread life state
Method locking
Mutex details
-
If the synchronization method does not use static modification, the default object is this
If the method is decorated with static, the default lock object is the current class class -
Landing steps:
- You need to analyze the locked code first
- Select synchronization code block or synchronization method
- It is required that the lock object of multiple threads is the same. It must be ensured that the lock on the thread is a shared lock and is the same object. Otherwise, it will not affect each other
- Release the lock the following actions will not release the lock
When a thread executes a synchronous code block or synchronous method, the program calls thread sleep() Thread. The yield () method pauses the execution of the current thread and does not release the lock
Case: I was too sleepy to go to the toilet and narrowed in the pit for a while
- When a thread executes a synchronous code block, other threads call the thread's suspend() method to suspend the thread, and the thread will not release the lock.
- Tip: try to avoid using suspend() and resume() to control threads. This method is no longer recommended
When thread synchronization method. Synchronous code block execution end case: go to the bathroom and come out when you're done
-
The current thread encountered a break and return in the synchronization code block and synchronization method
Case: without normal completion, the manager asked him to modify the bug. Have to come out -
The current thread has an unhandled Error or Exception in the synchronization code block and synchronization method, resulting in an abnormal end
Case: without normal completion, I found that I forgot to bring paper and had to come out -
The current thread synchronizes the code block. The wait() method of the thread object is executed in the synchronization method. The current thread pauses and releases the lock
Case: I didn't finish it normally and felt that I needed to brew, so I came out and went in later
- Synchronous code block
synchronized(object){ // Get the lock of the object to operate the synchronization code // Code to be synchronized }
- Synchronized can also be placed in a method declaration to represent the entire method - a synchronized method
How to understandpublic synchronized void m(String name){ // Code to be synchronized }
Just like Internet cafes, when they are used (locked), they are used (unlocked) by the next person who makes a reservation
Before locking
package Com.JW.Demo; /** * Lock the thread * * @author think * */ public class Demo11 { public static void main(String[] args) { sell_ticket ticket = new sell_ticket(); // sell_ticket ticket1 = new sell_ticket(); // sell_ticket ticket2 = new sell_ticket(); // // ticket.start(); // ticket1.start(); // ticket2.start(); Thread thread = new Thread(ticket); Thread thread1 = new Thread(ticket); Thread thread2 = new Thread(ticket); thread.start(); thread1.start(); thread2.start(); } } class sell_ticket extends Thread { int ticketNum = 100; @Override public void run() { // synchronized (this) { while (true) { if (ticketNum <= 0) { System.out.println("The tickets have been sold out!!!"); break; } try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "One ticket sold at the window, the rest" + (ticketNum--)); // } } } }
After locking
package Com.JW.Demo; /** * Lock the thread * * @author think * */ public class Demo11 { public static void main(String[] args) { sell_ticket ticket = new sell_ticket(); // sell_ticket ticket1 = new sell_ticket(); // sell_ticket ticket2 = new sell_ticket(); // // ticket.start(); // ticket1.start(); // ticket2.start(); Thread thread = new Thread(ticket); Thread thread1 = new Thread(ticket); Thread thread2 = new Thread(ticket); thread.start(); thread1.start(); thread2.start(); } } class sell_ticket extends Thread { int ticketNum = 100; @Override public void run() { synchronized (this) { while (true) { if (ticketNum <= 0) { System.out.println("The tickets have been sold out!!!"); break; } try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "One ticket sold at the window, the rest" + (ticketNum--)); } } } }
mutex
-
In java language, the concept of object mutex is introduced to ensure the integrity of shared data operation
-
Each object corresponds to a tag called "mutex", which is used to ensure that only one thread can access the object at any time
-
The keyword synchronized is associated with the mutex of an object. When an object is decorated with synchronized, it indicates that the object can only be accessed by one thread at any time
-
The limitation of synchronization leads to the reduction of program execution efficiency
-
The synchronous method (non static) lock can be this or other objects (the same object is required)
-
The lock of the synchronous method (static) is the class itself
package Com.JW.Demo.xiancheng; import java.util.Scanner; /** * Job 2 thread synchronization problem * * @author think * */ public class Work2 { public static void main(String[] args) { sell sell = new sell(); Thread thread = new Thread(sell); Thread thread1 = new Thread(sell); thread.start(); thread1.start(); } } class sell implements Runnable { private int count = 15000; int res = 0; // Scanner sc = new Scanner(System.in); @Override public void run() { while (true) { // 1. synchronized is used to synchronize threads // 2. When multiple threads execute here, they will compete for the lock of this object // 3. The thread that competes for (obtains) the lock of this object will execute the synchronized code block. After execution, release the lock of this object // 4. this object lock cannot be contested. Just blocked, ready to continue the fight synchronized (this) { if (count == 0) { System.out.println("Account balance is 0"); break; } // res = sc.nextInt(); count = count - 1000; System.out.println(Thread.currentThread().getName() + "Withdraw 1000 yuan"); try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
Thread resource contention simulates thread deadlock
Case test Ipackage Com.JW.Demo.xiancheng; /** * Simulating thread deadlock and resource contention * @author think * */ public class Demo1 { public static void main(String[] args) { T t = new T(); T t1 = new T(); t.start(); t1.loop = false; t1.start(); } } class T extends Thread { static Object a = new Object(); static Object b = new Object(); boolean loop = true; @Override public void run() { if (loop) { synchronized (a) { System.out.println(" Enter thread 1"); synchronized (b) { System.out.println(" Enter thread 2"); } } } else { synchronized (b) { System.out.println(" Enter thread 3"); synchronized (a) { System.out.println(" Enter thread 4"); } } } } }
Two threads thread A randomly outputs 1-100 digital thread B monitors thread A, and input Q stops thread A
Case test IIpackage Com.JW.Demo.xiancheng; import java.util.Random; import java.util.Scanner; /** * Assignment 1 * Two threads A randomly output numbers of 1-100 * Thread B monitors thread A, and input Q stops thread A * @author think * */ public class Work1 { public static void main(String[] args) throws InterruptedException { A a = new A(); B b = new B(a); a.start(); b.start(); // T_1 t = new T_1(); // Thread thread = new Thread(t); // thread.start(); // Scanner sc = new Scanner(System.in); // int in_num = sc.nextInt(); // while (true) { // Thread.sleep(30); // if (in_num == 1) { // t.loop = false; // // break; // } // } } } class A extends Thread { boolean loop = true; int num = 1; Random random = new Random(); @Override public void run() { while (loop) { num = random.nextInt(100) + 1; System.out.println(Thread.currentThread().getName() + " :" + num); try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "The thread stopped"); } } } } class B extends Thread { private A a ; public B(A a) { this.a = a; } Scanner sc = null; @Override public void run() { while (true) { System.out.println("Please enter"); sc = new Scanner(System.in); if (sc.next().toLowerCase().charAt(0) == 'q') { a.loop = false; System.out.println("b Thread stop"); break; } try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } class T_1 implements Runnable { boolean loop = true; int num = 1; Random random = new Random(); @Override public void run() { while (loop) { num = random.nextInt(100) + 1; System.out.println(Thread.currentThread().getName() + " :" + num); try { Thread.sleep(300); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println(Thread.currentThread().getName() + "The thread stopped"); } } } }
Thread synchronization problem
package Com.JW.Demo.xiancheng; import java.util.Scanner; /** * Job 2 thread synchronization problem * * @author think * */ public class Work2 { public static void main(String[] args) { sell sell = new sell(); Thread thread = new Thread(sell); Thread thread1 = new Thread(sell); thread.start(); thread1.start(); } } class sell implements Runnable { private int count = 15000; int res = 0; // Scanner sc = new Scanner(System.in); @Override public void run() { while (true) { // 1. synchronized is used to synchronize threads // 2. When multiple threads execute here, they will compete for the lock of this object // 3. The thread that competes for (obtains) the lock of this object will execute the synchronized code block. After execution, release the lock of this object // 4. this object lock cannot be contested. Just blocked, ready to continue the fight synchronized (this) { if (count == 0) { System.out.println("Account balance is 0"); break; } // res = sc.nextInt(); count = count - 1000; System.out.println(Thread.currentThread().getName() + "Withdraw 1000 yuan"); try { Thread.sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }