2、线程的并发工具类-CountDownLatch和CyclicBarrier辨析

你离开我真会死。 提交于 2020-02-06 13:24:50

CountDownLatch作用、应用场景和实战

CountDownLatch

作用:是一组线程等待其他的线程完成工作以后再执行,加强版join()

await 用来等待,countDown 负责计数器的减一

UseCountDownLatch

package com.xiangxue.ch2.tools;

import java.util.concurrent.CountDownLatch;

import com.xiangxue.tools.SleepTools;

/**
 *
 *类说明:演示CountDownLatch,有5个初始化的线程,6个扣除点,
 *扣除完毕以后,主线程和业务线程才能继续自己的工作
 */
public class UseCountDownLatch {
	
	static CountDownLatch latch = new CountDownLatch(6); //6个扣除点

	//初始化线程(只有一步,有4个)
    private static class InitThread implements Runnable{

        @Override
        public void run() {
        	System.out.println("Thread_"+Thread.currentThread().getId()
        			+" ready init work......");
        	latch.countDown();//初始化线程完成工作了,countDown方法只扣减一次;
            for(int i =0;i<2;i++) {
            	System.out.println("Thread_"+Thread.currentThread().getId()
            			+" ........continue do its work");
            }
        }
    }
    
    //业务线程
    private static class BusiThread implements Runnable{

        @Override
        public void run() {
        	try {
				latch.await(); //
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
            for(int i=0;i<3;i++) {
            	System.out.println("BusiThread_"+Thread.currentThread().getId()
            			+" do business-----");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
    	//单独的初始化线程,初始化分为2步,需要扣减两次
        new Thread(new Runnable() {
            @Override
            public void run() {
            	SleepTools.ms(100);//因为有时间延迟,所以每次执行在初始化线程里都靠后
                System.out.println("Thread_"+Thread.currentThread().getId()
            			+" ready init work step 1st......");
                latch.countDown();//每完成一步初始化工作,扣减一次
                System.out.println("begin step 2nd.......");
                SleepTools.ms(100);
                System.out.println("Thread_"+Thread.currentThread().getId()
            			+" ready init work step 2nd......");
                latch.countDown();//每完成一步初始化工作,扣减一次
            }
        }).start();
        new Thread(new BusiThread()).start(); //业务线程代码位置在初始化线程代码之上,执行顺序却靠后
        for(int i=0;i<4;i++){
            Thread thread = new Thread(new InitThread()); //循环执行创建4次的初始化线程
            thread.start();
        }

        latch.await(); //业务线程和主线程(没有设定延时)执行顺序是平级的。
        System.out.println("Main do ites work........");
    }
}

 

SleepTools

package com.xiangxue.tools;

import java.util.concurrent.TimeUnit;

/**
 * 
 *
 *类说明:线程休眠辅助工具类
 */
public class SleepTools {
	
	/**
	 * 按秒休眠
	 * @param seconds 秒数
	 */
    public static final void second(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
        }
    }
    
    /**
     * 按毫秒数休眠
     * @param seconds 毫秒数
     */
    public static final void ms(int seconds) {
        try {
            TimeUnit.MILLISECONDS.sleep(seconds);
        } catch (InterruptedException e) {
        }
    }
}

CyclicBarrier作用、应用场景和实战

CyclicBarrier

让一组线程达到某个屏障,被阻塞,一直到组内最后一个线程达到屏障时,屏障开放,所有被阻塞的线程会继续运行CyclicBarrier(int parties)

CyclicBarrier(int parties, Runnable barrierAction),屏障开放,barrierAction定义的任务会执行

CountDownLatch和CyclicBarrier辨析

1、countdownlatch放行由第三者控制,CyclicBarrier放行由一组线程本身控制
2、countdownlatch放行条件>=线程数,CyclicBarrier放行条件=线程数

UseCyclicBarrier

package com.xiangxue.ch2.tools;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;

/**
 *
 *类说明:CyclicBarrier的使用
 */
public class UseCyclicBarrier {
	
	private static CyclicBarrier barrier 
		= new CyclicBarrier(5,new CollectThread());
	
    private static ConcurrentHashMap<String,Long> resultMap
            = new ConcurrentHashMap<>();//存放子线程工作结果的容器
    //main函数
    public static void main(String[] args) { 
        for(int i=0;i<5;i++){ //循环执行,创建5次子线程并启动
            Thread thread = new Thread(new SubThread());  
            thread.start();
        }

    }

    //负责屏障开放以后的工作
    private static class CollectThread implements Runnable{

        @Override
        public void run() {
            StringBuilder result = new StringBuilder();
            //增强for循环遍历
            for(Map.Entry<String,Long> workResult:resultMap.entrySet()){
            	result.append("["+workResult.getValue()+"]");
            }
            System.out.println(" the result = "+ result);
            System.out.println("do other business........");
        }
    }

    //工作线程
    private static class SubThread implements Runnable{

        @Override
        public void run() {
        	long id = Thread.currentThread().getId(); //获取线程本身的id
            resultMap.put(Thread.currentThread().getId()+"",id);
            Random r = new Random();
            try {
                if(r.nextBoolean()) {//随机决定工作线程的是否睡眠
                	Thread.sleep(2000+id);
                	System.out.println("Thread_"+id+" ....do something ");
                }
                System.out.println(id+"....is await");
                barrier.await();
            	Thread.sleep(1000+id);
                System.out.println("Thread_"+id+" ....do its business ");
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

 

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