当前位置:网站首页>Day22 deadlock, thread communication, singleton mode

Day22 deadlock, thread communication, singleton mode

2022-07-07 12:48:00 Xiaobai shelter

1. Deadlock
1.1 summary
Deadlock : Is in the process of execution , Both encountered the other party's method of locking , This leads to a state that everyone can't access

principle : 1. The execution of a thread is completed , Two objects need to be nested and locked successively , And in the process , Lock the first object first
2. The execution of another thread is completed , Two objects need to be nested and locked successively , And in the process , Lock the second object first
3. When the first thread executes to the second object , Found locked , Can only wait for
4. When the second thread executes to the first object , Found locked , Can only wait for

1.2 Code implementation

public class Thread_01_DeadLock {
    
   public static void main(String args[]){
    
	   Object o1=new Object();
	   Object o2=new Object();
	   Thread t1=new Thread(new Thread_01(o1,o2));
	   Thread t2=new Thread(new Thread_02(o1,o2));
	   t1.setName("t1");
	   t2.setName("t2");
	   t1.start();
	   t2.start();
   }
}
class Thread_01 implements Runnable{
    
   Object o1;
   Object o2;

	public Thread_01(Object o1, Object o2) {
    
	this.o1 = o1;
	this.o2 = o2;
}

	public void run() {
    
		synchronized(o1){
    
			try {
    
				Thread.sleep(100);
			} catch (InterruptedException e) {
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		synchronized(o2){
    
			System.out.println(Thread.currentThread().getName()+" Execution completed ");
		}	
		}
	}
}
class Thread_02 implements Runnable{
    
	Object o1 ;
	Object o2;
	public Thread_02(Object o1, Object o2) {
    
		this.o1 = o1;
		this.o2 = o2;
	}

	@Override
	public void run() {
    
		synchronized (o2) {
    
			try {
    
				Thread.sleep(100);
			} catch (InterruptedException e) {
    
				e.printStackTrace();
			}
			synchronized (o1) {
    
				System.out.println(Thread.currentThread().getName()+" Execution completed ");
			}
		}
	}
}

2. Thread communication
2.1 summary
wait: Put the thread into a waiting state , Locks held are released
No participation or introduction 0 To wait for , Will not wake up automatically , Can only wait notify Wake up it
Can also be passed in long Type value , Be similar to sleep, It's time to wake yourself up
notify: Randomly wake up a thread waiting in the object
notifyAll: Wake up all waiting threads in the object
The above methods can only be used for member methods with locks
2.2 Usage mode

 demand :  Print odd and even numbers 
 *         1. There is a business class , There is a way to print odd and even numbers 
 *         2. There is a variable  count Record the current number 
 *         3. Two threads , Call the methods of printing odd and even numbers respectively 


 */
public class Thread_02_wait {
    
    public static void main(String args[]){
    
    	// Create reference type variables  Num It's a class   Class is a reference type   There are also array interfaces 
    	Num num=new Num();
    	Thread t1=new PrintEven(num);
    	Thread t2=new PrintOdd(num);
    	t1.setName("t1");
    	t2.setName("t2");
    	t1.start();
    	t2.start();
    }
}
// Print odd threads 
class PrintOdd extends Thread{
    
	Num num;
	public PrintOdd(Num num){
    
		this.num=num;
	}
	public void run(){
    
		while(true){
    
			num.printOdd();
		}
	}
}
// Print even threads 
class PrintEven extends Thread{
    
	Num num;
	public PrintEven(Num num){
    
		this.num=num;
	}
public void run(){
    
		while(true){
    
			num.printEven();
		}
	}
}

// 1. There is a business class 
class Num{
    
	// There is a variable  count Record the current number 
	int count=1;
	// How to print odd numbers 
	public synchronized void printOdd(){
    
		System.out.println(Thread.currentThread().getName()+"-->"+count);
		count++;
		// Wake up other threads , Go and inquire about even numbers 
		this.notifyAll();
		// Has reached the awaited 
		try {
    
			Thread.sleep(1000);
			this.wait();
		} catch (InterruptedException e) {
    
			e.printStackTrace();
		}
		
	}
	// Print even numbers 
	public synchronized void printEven(){
    
		System.out.println(Thread.currentThread().getName()+"-->"+count);
		count++;
		// Wake up other threads , To print odd numbers 
		this.notifyAll();
		// Has reached the awaited 
		try {
    
			Thread.sleep(1000);
			this.wait();
		} catch (InterruptedException e) {
    
			e.printStackTrace();
		}
	}
}

2.3 producers and consumers
For details, see :https://blog.csdn.net/qq_39575279/article/details/87940298

The main thing is to reduce the coupling

 * 1. A business class SynStack  There's a variable ,
 *    Used to save the number of produced elements 
 * 2. There is one in the business class char Array , Used to save production elements 
 *   ( If only produce a-z These letters )
 * 3. There need to be two methods in the business class , A production push, A consumer pop
 *     push Method   It is mainly used to add data to the array 
 *        Number to +1, Also determine whether it is full ,
 *        When it's full, hang up and wait 
 *     pop Method      It is mainly used to fetch the data in the array 
 *          Number to -1, But also to determine whether the consumption is over ,
 *          When it's over, hang up and wait 
 * 4. Two threads , One is responsible for the production of , One is responsible for consumption 

 */
public class Thread_03_ProducerConsumer {
    
    public static void main(String args[]){
    
    	SynStack ss=new SynStack();
    	Thread p=new Thread(new Producer(ss));
    	Thread c=new Thread(new Consumer(ss));
    	p.start();
    	c.start();
    }
}
// Producer method 
class Producer implements Runnable{
    
    SynStack ss;
    public Producer(SynStack ss){
    
    	this.ss=ss;
    }
	@Override
	public void run() {
    
     Random random=new Random();
     while(true){
    
    	 char ch=(char) (random.nextInt(26)+97);
    	 ss.push(ch);
     }	
	}	
}
// Consumer approach 
class Consumer implements Runnable{
    
	SynStack ss;
	public Consumer(SynStack ss){
    
		super();
		this.ss=ss;
	}
	@Override
	public void run() {
    
       while(true){
    
    	   try {
    
			Thread.sleep(500);
		} catch (InterruptedException e) {
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	   ss.pop();
       }
		
	}
}
// Let's start with a business class 
class SynStack{
    
	// Container for saving data 
	char[] data=new char[6];
	// Number of production 
	int count=0;
	// production 
	public synchronized void push(char ch){
    
		// Judge whether it is full 
		if(count==data.length){
    
			try {
    
				this.wait();
			} catch (InterruptedException e) {
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// That means it's not full , Started to produce 
		// Awaken consumers to prepare for consumption 
		this.notifyAll();
		data[count]=ch;
		count++;
		System.out.println(" Produced "+ch+", The remaining "+count+" Elements ");
	}
	// Consumption method 
	public synchronized char pop(){
    
		// Determine whether it is null 
		if(count==0){
    
			try {
    
				// There's no need to wake up the producers here , Because the producer is full in wait, It's all empty , It means that the producer must not wait
				
				this.wait();
			} catch (InterruptedException e) {
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		// This is not empty , Start spending 
		count--;
		char ch=data[count];
		// Wake up producers 
		this.notifyAll();
		System.out.println(" The consumption "+ch+", The remaining "+count+" Elements ");
		return ch;
	}
}

3. The singleton pattern
The singleton pattern : Let a class instantiate only one object
The constructor is privatized , Static variables hold objects , Public static methods are used to get class objects

  Hungry man mode has no problem in a multithreaded environment , Because no matter how many thread classes can only be loaded once , So it will only be initialized once ,
 *  This means that only one object can be created 

 */
public class Thread_04_SingLeton {
    
   private Thread_04_SingLeton(){
    
	   
   }
   
   private static Thread_04_SingLeton singLeton=new Thread_04_SingLeton();
   public static Thread_04_SingLeton getInstance() {
    
		return singLeton;
	}
/** * volatile :  Why use volatile Well ?  Prevent command rearrangement  * * https://www.cnblogs.com/dolphin0520/p/3920373.html * */
	private volatile static Thread_05_SingLeton singLeton = null;

	//  Low efficiency , Because you have to queue up every time 
	// public synchronized static Thread_05_SingLeton getInstance() {
    
	// if (singLeton == null) {
    
	// singLeton = new Thread_05_SingLeton();
	// }
	// return singLeton;
	// }

	//  More efficient , Because you only need to queue for the first time 
	public static Thread_05_SingLeton getInstance() {
    

		if (singLeton == null) {
    

			synchronized (Thread_05_SingLeton.class) {
    
				// 1// 2
				if (singLeton == null) {
    
					singLeton = new Thread_05_SingLeton();
				}
			}
		}

		return singLeton;
	}
}

4. Thread pool
 Insert picture description here
Single threaded pool (newSingleThreadExecutor) The advantages of , Serial execution of all tasks . If the only thread ends because of an exception , Then there will be a new thread to replace it
This thread pool ensures that all tasks are executed in the order in which they are submitted

原网站

版权声明
本文为[Xiaobai shelter]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130617040308.html