多线程-1117

穿精又带淫゛_ 提交于 2020-10-31 05:58:50

规律:

多线程协作中,一般被考虑使用的,无非就是:

    (同步工具类) Semaphore(  semaphore.acquire();消耗许可数,许可数为负数时,当前线程将被阻塞  semaphore.release();增加许可数 )

                         CountDownLatch( countDown.countDown() 初始值减1,当前线程总是不会被阻塞  countDown.await()若值不为0则会被阻塞,等待初始值减为0才会恢复 )

                         CyclicBarrier( cyclicBarrier.await() 初始值减1,并阻塞等待初始值减为0。最后一个线程将它减为0之后,若有指定任务,则还需要负责执行指定任务完毕,之后会唤醒之前被阻塞的所有线程,并重置为初始值。 

                         有两个构造方法,其中一个构造方法可以指定每次最后一个线程,需要执行的额外任务。

                        

                                                cyclicBarrier.reset() 用于提前唤醒被阻塞的线程,并重置为初始值 )

    (原子变量类) AtomicInteger 一般用于无锁进行自增计数情形

    (锁) volatile + (ReentrantLock + Condition) / synchronized 

             通过 condition.await()/condition.signal()  或者 object.wait()/object.notify() 的 挂起/通知机制 来完成线程协作。 

 

1.凡是可以用semaphore解决的问题,大多都可以使用管程(也就是lock)来解决,但使用lock需要增加一个变量来标记起始条件.

    该变量的作用:决定哪一个线程先执行第一次,其他的线程此时应当阻塞或者挂起。

2.凡是可以使用多个condition可以解决的问题,都可以使用一个condition和一个volatile变量来解决

    一个condition,在唤起的时候,只能调用 notifyAll()。此时这个volatile变量将用于判断被唤醒的线程中,哪些线程是我们期望接下来继续执行的;而其余的线程应当再次被挂起。

 

    实现1:信号量 + Atomic(计数)

class H2O {
    // Initialize hydrogen group (H20) limit.限制了最多可执行2次
    private Semaphore semaH = new Semaphore(2);
    // Initialize oxygen group (H2O) limit.限制了最多可执行1次
    private Semaphore semaO = new Semaphore(1);
    
    // Initialize group count.记录每一次生成水分子的进度
    private AtomicInteger groupCount = new AtomicInteger(0);
    
    private static final int GROUP_H_LIMIT = 2;
    private static final int GROUP_O_LIMIT = 1;
    private static final int GROUP_TOTAL_LIMIT = GROUP_H_LIMIT + GROUP_O_LIMIT;
    
    public H2O() {
    }

    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
        // Try to acquire hygrogen permit.
        this.semaH.acquire(1);
    
        // releaseHydrogen.run() outputs "H". Do not change or remove this line.
        releaseHydrogen.run();
    
        // Increment group molecule count.
        this.groupCount.incrementAndGet();
        
        //检查是否已生成了一个完整的水分子
        resetIfNeeded();
    }

    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        this.semaO.acquire(1);
        
        // releaseOxygen.run() outputs "O". Do not change or remove this line.
	    releaseOxygen.run();
        
        this.groupCount.incrementAndGet();
        
        //检查是否已生成了一个完整的水分子
        resetIfNeeded();
    }
    
    //只有这个方法,会给两个信号量增加许可数
    private void resetIfNeeded() {
        // If the current group is ready, release permits and try another. 
        if (this.groupCount.compareAndSet(GROUP_TOTAL_LIMIT, 0)) {
            this.semaH.release(GROUP_H_LIMIT);
            this.semaO.release(GROUP_O_LIMIT);
        }
    }
}

    实现2:信号量 + CyclicBarrier (计数)

class H2O {
    //只要CyclicBarrier达到计数值3,就执行semaphoreH和semaphoreO许可证颁发
    private CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
        @Override
        public void run() {
            semaphoreH.release(2);
            semaphoreO.release();
        }
    });

    private Semaphore semaphoreH;
    private Semaphore semaphoreO;
    
    public H2O() {
        //确保H至多执行2次,O至多执行1次
        semaphoreH = new Semaphore(2);
        semaphoreO = new Semaphore(1);
    }

    
    public void hydrogen(Runnable releaseHydrogen) throws InterruptedException {
        //此处只消耗许可证,颁发许可证交由CyclicBarrier
        semaphoreH.acquire();

        // releaseHydrogen.run() outputs "H". Do not change or remove this line.
        releaseHydrogen.run();

        try {
            //增加CyclicBarrier的计数
            barrier.await();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public void oxygen(Runnable releaseOxygen) throws InterruptedException {
        //此处只消耗许可证,颁发许可证交由CyclicBarrier
        semaphoreO.acquire();
        
        // releaseOxygen.run() outputs "O". Do not change or remove this line.
        releaseOxygen.run();
        
        try {
            //增加CyclicBarrier的计数
            barrier.await();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!