多线程常见用例
1.懒汉式单例双重校验实现
1.1 代码:
class Bank_LanHan{
private static Bank_LanHan BankObject = null;
private Bank_LanHan(){
}
public static Bank_LanHan getBankObject(){
if(BankObject == null){
synchronized(Bank_LanHan.class){
if(BankObject == null){
BankObject = new Bank_LanHan();
}
}
}
return BankObject;
}
}
1.2 双重校验的优势
1.3 执行过程
- 首先有一个线程进入到第一重if里面正要获取锁后面又有多个线程进来想要获取锁(姑且先把第一个线程称为a,后来进来的线程为b,c)
- 线程a获取到锁,进入到二层循环中去 创建单例实例,之后线程a释放锁
- 线程b,c相继获取到锁,如果没有二重校验b,c就会再次创建实例 就不是单例了
后面的再来的d、e之类的线程只需要第一重校验就会发现实例不是为空直接就可以返回了,不用都获取锁,这就是双重校验性能会好一点的愿意
2. 生产者和消费者
/** * @author zongzhaojin * @date 2022/4/15 17:36 */ public class product_customer { public static void main(String[] args) { Clerk clerk = new Clerk(); Producer producer = new Producer(clerk); Customer customer = new Customer(clerk); Thread thread = new Thread(producer); Thread thread1 = new Thread(customer); thread.start(); thread1.start(); } } class Clerk{ int product_num = 0; public synchronized void produceProduct() { if(product_num < 20){ product_num++; notify(); System.out.println(Thread.currentThread().getName()+":开始生产"+product_num); }else{ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void consumeProduct() { if(product_num > 0 ){ product_num--; notify(); System.out.println(Thread.currentThread().getName()+":开始消费"+product_num); }else{ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Producer implements Runnable { Clerk clerk; public Producer(Clerk clerk){ this.clerk = clerk; } @Override public void run() { while (true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerk.produceProduct(); } } } class Customer implements Runnable{ Clerk clerk; public Customer(Clerk clerk){ this.clerk = clerk; } @Override public void run() { while (true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerk.consumeProduct(); } } }