• 呀?这就是锁(二)?


    java常用锁

    CountDownLatch(倒数计数器,门栓)

    package AboutSysn;
    
    import java.util.concurrent.CountDownLatch;
    
    public class CountDownLatchDemo {
    	
    	public static void main(String[] args) {
    	
    		CountDownLatch cdl = new CountDownLatch(2); //添加两道栅栏,
    		for(int i = 0;i<5;i++) {
    			new Thread(()->{
    				System.out.println(Thread.currentThread().getName()+"-----1");
    				if(cdl.getCount()>0) {
    					cdl.countDown();	//释放一层栅栏
    				}
    				try {
    					cdl.await();	//等待栅栏全部释放后,才可以继续执行
    					
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    				System.out.println(Thread.currentThread().getName()+"-----2");
    			}).start();;
    		}
    		
    		
    	}
    }
    

    总结:

    CountDownLatch 维护了一个int变量,当这个变量等于0是,所有等待这个变量的线程开始运行。等待的过程使用的是CAS,这个最后写到AQS时详说,现在只需要明白只要线程执行了 cdl.await,其背后的意义就是告诉这个线程你要等待 cdl 的 count 的值变成0。

    CyclicBarrier(同步屏障)

    package AboutSysn;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;
    
    public class CyclicBarrierDemo {
    
    	public static void main(String[] args) {
    		CyclicBarrier cb = new CyclicBarrier(2);
    		List<Thread> threads = new ArrayList<Thread>();
    		for(int i = 0;i<6;i++) {
    		Thread t = new Thread(()->{
    				
    				System.out.println(Thread.currentThread().getName()+"到达");
    				try {
    					cb.await(); //等待其他线程到达
    					System.out.println(Thread.currentThread().getName()+"执行了");
    				} catch (InterruptedException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				} catch (BrokenBarrierException e) {
    					// TODO Auto-generated catch block
    					e.printStackTrace();
    				}
    			});
    		threads.add(t);
    		}
    		
    		threads.forEach(o->{
    			o.start();
    			try {
    				Thread.sleep(1000);
    				System.out.println(o.getName()+"开始执行");
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		});
    		
    	}
    }
    //结果 这个结果还能证明指令重排序,优秀!!!!
    Thread-0到达
    Thread-0开始执行
    Thread-1到达
    Thread-1执行了
    Thread-0执行了
    Thread-1开始执行
    Thread-2到达
    Thread-2开始执行
    Thread-3到达
    Thread-3执行了
    Thread-2执行了
    Thread-3开始执行
    Thread-4到达
    Thread-4开始执行
    Thread-5到达
    Thread-5执行了
    Thread-4执行了
    Thread-5开始执行
    

    总结:

    我们可以使用CyclicBarrier使需要彼此配合的线程协同工作,例如ThreadA的计算需要ThreadB的部分结果就可以这样使用。相当于增强的CountDownLatch

    Phaser

    package AboutSysn;
    
    import java.util.concurrent.Phaser;
    
    public class PhaserDemo {
    
    	static Phaser p = new MyPhaser();
    	//看电影
    	static class MyPhaser extends Phaser{
    		protected boolean onAdvance(int phase, int registeredParties) {
    			
    			System.out.println(phase+"--"+registeredParties);
    			switch (phase) {
    			case 0:
    				//这里进行所有线程都要执行的任务
    				System.out.println("所有人进场");
    				return  false;
    			case 1:
    				System.out.println("观看电影");
    				return false;
    			case 2:
    				//这里执行只有管理员线程要做的任务
    				System.out.println("除管理员,其他人离场");
    				return true;
    			default:
    				return true;
    			}
    		}
    		
    	}
    	public static void main(String[] args) {
    		p.bulkRegister(5); //p会拦截5个线程然后放行
    		Runnable r = new Runnable() {
    			void m1() {
    				System.out.println("m1");
    				p.arriveAndAwaitAdvance();
    			}
    			void m2() {
    				System.out.println("m2");
    				p.arriveAndAwaitAdvance();
    			}
    			void m3() {
    				System.out.println("m3");
    				String name = Thread.currentThread().getName();
    				if(!name.equals("Thread-4")) {
    					p.arriveAndDeregister(); //游客线程去掉
    				}else {
    					p.arriveAndAwaitAdvance(); //管理员线程保留
    				}
    			}
    			@Override
    			public void run() {
    				// TODO Auto-generated method stub
    				m1(); //第一次栅栏拦截,
    				m2(); //第二次栅栏拦截
    				m3(); //第三次栅栏拦截
    			}
    		};
    		
    		for(int i=0;i<5;i++)
    		{
    			new Thread(r).start();;
    		}
    	}
    }
    //结果
    m1
    m1
    m1
    m1
    m1
    0--5
    所有人进场
    m2
    m2
    m2
    m2
    m2
    1--5
    观看电影
    m3
    m3
    m3
    m3
    m3
    2--1
    除管理员,其他人离场
    
    

    总结:

    Phaser其本质和另外两种没有什么区别,相当于增强了CyclicBarrier,可以在过程中对拦截线程数量进行动态的调整,可以让一部分线程做一个特殊的任务。

  • 相关阅读:
    【UOJ Round #3】
    【UOJ Round #1】
    【BZOJ】【3673】可持久化并查集 & 【3674】可持久化并查集加强版
    【ContestHunter】【弱省胡策】【Round7】
    【BZOJ】【3211】花神游历各国
    【BZOJ】【4146】 【AMPPZ2014】Divisors
    【BZOJ】【3931】【CQOI2015】网络吞吐量
    【BZOJ】【3697】采药人的路径&【3127】【USACO2013 Open】Yin and Yang
    【BZOJ】【3930】【CQOI2015】选数
    【ContestHunter】【弱省胡策】【Round6】
  • 原文地址:https://www.cnblogs.com/aierben/p/14754534.html
Copyright © 2020-2023  润新知