JAVA基础—JUC包(java.util.concurrent)

1. JUC - CountDownLatch 倒计时锁

/**
 * 倒计时锁
 */
public class CountDownLatchSample {
    private static int count = 0;

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(100);
        CountDownLatch countDownLatch = new CountDownLatch(10000);
        for (int i = 1; i <= 10000; i++) {
            final int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    //多个线程运行时 代码需要同步
                    synchronized (CountDownLatchSample.class){
                        try {
                            count = count + index;
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            countDownLatch.countDown();
                        }
                    }
                }
            });
        }

        //倒计时锁await()结束后才继续往后执行
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(count);
        //关闭线程池
        threadPool.shutdown();
    }

}

运行结果

50005000

2. JUC之Semaphore信号量

/**
 * Semaphore信号量经常用于限制获取某种资源的线程数量
 */
public class SemaphoreSample {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(5);//定义5个信号量
        for (int i = 1; i <= 20; i++) {
            final int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();//获取一个信号量,"占用一个跑道"
                        play();
                        semaphore.release();//执行完成后,释放这个信号量
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        //关闭线程池
        threadPool.shutdown();

    }

    public static void play() {
        try {
            System.out.println(new Date() + " " + Thread.currentThread().getName() + ":获得进入服务器资格");
            Thread.sleep(2000);
            System.out.println(new Date() + " " + Thread.currentThread().getName() + ":退出服务器");
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

Wed Aug 08 12:08:16 CST 2018 pool-1-thread-7:退出服务器
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-10:退出服务器
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-11:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-14:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-15:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-18:获得进入服务器资格
Wed Aug 08 12:08:16 CST 2018 pool-1-thread-19:获得进入服务器资格
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-11:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-14:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-19:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-18:退出服务器
Wed Aug 08 12:08:18 CST 2018 pool-1-thread-15:退出服务器

---------------------------------------------------------------------

/**
  信号量已满时 不再执行其它线程
*/
public class SemaphoreSample {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(5);//定义5个信号量
        for (int i = 1; i <= 20; i++) {
            final int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    if (semaphore.tryAcquire()) {//尝试获取一次信号量,获取到返回true,否则返回false
                        play();
                        semaphore.release();//执行完成后,释放这个信号量
                    } else {
                        System.out.println(Thread.currentThread().getName() + ":对不起服务器已满,请稍后再试");
                    }
                }
            });
        }

        //关闭线程池
        threadPool.shutdown();

    }

    public static void play() {
        try {
            System.out.println(new Date() + " " + Thread.currentThread().getName() + ":获得进入服务器资格");
            Thread.sleep(2000);
            System.out.println(new Date() + " " + Thread.currentThread().getName() + ":退出服务器");
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

pool-1-thread-5:对不起服务器已满,请稍后再试
pool-1-thread-6:对不起服务器已满,请稍后再试
pool-1-thread-8:对不起服务器已满,请稍后再试
pool-1-thread-9:对不起服务器已满,请稍后再试
pool-1-thread-10:对不起服务器已满,请稍后再试
pool-1-thread-18:对不起服务器已满,请稍后再试
pool-1-thread-19:对不起服务器已满,请稍后再试
pool-1-thread-13:对不起服务器已满,请稍后再试
pool-1-thread-12:对不起服务器已满,请稍后再试
pool-1-thread-17:对不起服务器已满,请稍后再试
pool-1-thread-16:对不起服务器已满,请稍后再试
pool-1-thread-20:对不起服务器已满,请稍后再试
pool-1-thread-14:对不起服务器已满,请稍后再试
pool-1-thread-15:对不起服务器已满,请稍后再试
pool-1-thread-11:对不起服务器已满,请稍后再试
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-3:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-1:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-4:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-7:获得进入服务器资格
Wed Aug 08 12:14:51 CST 2018 pool-1-thread-2:获得进入服务器资格
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-1:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-7:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-4:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-2:退出服务器
Wed Aug 08 12:14:53 CST 2018 pool-1-thread-3:退出服务器

-------------------------------------------------------------------------------------

/**
 * 信号量已满时 不再执行其它线程
 */
public class SemaphoreSample {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        Semaphore semaphore = new Semaphore(5);//定义5个信号量
        for (int i = 1; i <= 20; i++) {
            final int index = i;
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        //尝试获取一次信号量,6秒钟内获取到返回true,否则返回false
                        if (semaphore.tryAcquire(6,TimeUnit.SECONDS)) {
                            play();
                            semaphore.release();//执行完成后,释放这个信号量
                        } else {
                            System.out.println(Thread.currentThread().getName() + ":对不起服务器已满,请稍后再试");
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        //关闭线程池
        threadPool.shutdown();

    }

运行结果

Wed Aug 08 12:22:55 CST 2018 pool-1-thread-4:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-3:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-6:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-2:获得进入服务器资格
Wed Aug 08 12:22:55 CST 2018 pool-1-thread-1:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-4:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-6:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-1:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-3:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-2:退出服务器
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-5:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-7:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-11:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-15:获得进入服务器资格
Wed Aug 08 12:22:57 CST 2018 pool-1-thread-10:获得进入服务器资格
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-5:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-11:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-7:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-10:退出服务器
Wed Aug 08 12:22:59 CST 2018 pool-1-thread-15:退出服务器
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-8:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-12:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-14:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-13:获得进入服务器资格
Wed Aug 08 12:23:00 CST 2018 pool-1-thread-9:获得进入服务器资格
pool-1-thread-17:对不起服务器已满,请稍后再试
pool-1-thread-20:对不起服务器已满,请稍后再试
pool-1-thread-19:对不起服务器已满,请稍后再试
pool-1-thread-18:对不起服务器已满,请稍后再试
pool-1-thread-16:对不起服务器已满,请稍后再试
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-8:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-12:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-14:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-13:退出服务器
Wed Aug 08 12:23:02 CST 2018 pool-1-thread-9:退出服务器

3. JUC之CyclicBarrier循环屏障

/**
 * CyclicBarrier循环屏障
 * 是一个同步工具类,它允许一组线程互相等待,知道到达某个公共屏障点
 * 与CountDawnLatch不同的是该barrier在释放等待线程后可以重用
 */
public class CyclicBarrierSample {
    //定义屏障点 5个线程
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        for (int i = 1; i <= 10; i++) {
            final int index = i;
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    go();
                }
            });
        }

        //关闭线程池
        threadPool.shutdown();
    }

    private static void go() {
        System.out.println(Thread.currentThread().getName() + " : 准备就绪");
        try {
            cyclicBarrier.await();//设置屏障点,当累计5个线程都准备好后,才运行后面的代码
            System.out.println(Thread.currentThread().getName() + " : 开始运行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

运行结果

pool-1-thread-1 : 准备就绪
pool-1-thread-2 : 准备就绪
pool-1-thread-3 : 准备就绪
pool-1-thread-4 : 准备就绪
pool-1-thread-5 : 准备就绪
pool-1-thread-5 : 开始运行
pool-1-thread-1 : 开始运行
pool-1-thread-3 : 开始运行
pool-1-thread-2 : 开始运行
pool-1-thread-4 : 开始运行
pool-1-thread-4 : 准备就绪
pool-1-thread-2 : 准备就绪
pool-1-thread-3 : 准备就绪
pool-1-thread-1 : 准备就绪
pool-1-thread-5 : 准备就绪
pool-1-thread-5 : 开始运行
pool-1-thread-4 : 开始运行
pool-1-thread-2 : 开始运行
pool-1-thread-1 : 开始运行
pool-1-thread-3 : 开始运行

4. JUC之Conditon线程等待与唤醒

/**
 * Codintion线程的等待与唤醒
 * 需要配合ReentrantLock 重入锁使用
 */
public abstract class ConditonSample {
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition condition1 = lock.newCondition();
        Condition condition2 = lock.newCondition();
        Condition condition3 = lock.newCondition();

        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    condition1.await();
                    Thread.sleep(1000);
                    System.out.println("粒粒皆辛苦");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {//重入锁需要手动解锁
                    lock.unlock();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    condition2.await();
                    Thread.sleep(1000);
                    System.out.println("谁知盘中餐");
                    condition1.signal();//唤醒c1
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {//重入锁需要手动解锁
                    lock.unlock();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    condition3.await();
                    Thread.sleep(1000);
                    System.out.println("汗滴禾下土");
                    condition2.signal();//唤醒c2
                }catch (Exception e){
                    e.printStackTrace();
                }finally {//重入锁需要手动解锁
                    lock.unlock();
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    Thread.sleep(1000);
                    System.out.println("锄禾日当午");
                    condition3.signal(); //唤醒c3
                }catch (Exception e){
                    e.printStackTrace();
                }finally {//重入锁需要手动解锁
                    lock.unlock();
                }
            }
        }).start();

    }
}

运行结果

锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦

5. JUC之Callable_Future

Callable&Future
public class Callable_Future_Sample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //打印1000以内的质数
        for (int i = 2; i <= 1000; i++) {
            Computor computor = new Computor();
            computor.setNum(i);
            //将computor对象提交给线程池,如果有空闲线程立即执行里面的call方法
            //Future是对用于计算的线程进行监听,应为计算时在其它线程中执行的,所以这个返回的结果时异步的
            Future<Boolean> submitResult = executorService.submit(computor);
            try {
                //用于获取返回值,如果线程池内部的call方法没有执行完成,则进入等待状态,知道计算完成
                Boolean r = submitResult.get();
                if (r == true) {
                    System.out.println(computor.getNum());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        //关闭线程池
        executorService.shutdown();
    }
}

class Computor implements Callable<Boolean> {
    private Integer num;

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    @Override
    public Boolean call() throws Exception {
        boolean isprime = true;
        for (int i = 2; i < num; i++) {
            if (num % i == 0) {
                isprime = false;
                break;
            }
        }
        return isprime;
    }
}

运行结果

2
3
5
7
11
13
17
19
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容