Java基础知识-java.util.concurrent包下常见类的使用

一,Condition

一个场景,两个线程数数,同时启动两个线程,线程A数1、2、3,然后线程B数4、5、6,最后线程A数7、8、9,程序结束,这涉及到线程之间的通信。

public class ConditionTest {
    static class NumberWrapper {
        public int value = 1;
    }

    public static void main(String[] args) {
        //初始化可重入锁
        final Lock lock = new ReentrantLock();

        //第一个条件当屏幕上输出到3
        final Condition reachThreeCondition = lock.newCondition();
        //第二个条件当屏幕上输出到6
        final Condition reachSixCondition = lock.newCondition();

        //NumberWrapper只是为了封装一个数字,一边可以将数字对象共享,并可以设置为final
        //注意这里不要用Integer, Integer 是不可变对象
        final NumberWrapper num = new NumberWrapper();
        //初始化A线程
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                //需要先获得锁
                lock.lock();
                System.out.println("ThreadA获得lock");
                try {
                    System.out.println("threadA start write");
                    //A线程先输出前3个数
                    while (num.value <= 3) {
                        System.out.println(num.value);
                        num.value++;
                    }
                    //输出到3时要signal,告诉B线程可以开始了
                    reachThreeCondition.signal();
                } finally {
                    lock.unlock();
                    System.out.println("ThreadA释放lock");
                }
                lock.lock();
                try {
                    //等待输出6的条件
                    System.out.println("ThreadA获得lock");
                    reachSixCondition.await();
                    System.out.println("threadA start write");
                    //输出剩余数字
                    while (num.value <= 9) {
                        System.out.println(num.value);
                        num.value++;
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                    System.out.println("ThreadA释放lock");
                }
            }

        });
        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock.lock();
                    System.out.println("ThreadB获得lock");
                    Thread.sleep(5000);//是await方法释放了锁
                    while (num.value <= 3) {
                        //等待3输出完毕的信号
                        reachThreeCondition.await();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                    System.out.println("ThreadB释放lock");
                }
                try {
                    lock.lock();
                    System.out.println("ThreadB获得lock");
                    //已经收到信号,开始输出4,5,6
                    System.out.println("threadB start write");
                    while (num.value <= 6) {
                        System.out.println(num.value);
                        num.value++;
                    }
                    //4,5,6输出完毕,告诉A线程6输出完了
                    reachSixCondition.signal();
                } finally {
                    lock.unlock();
                    System.out.println("ThreadB释放lock");
                }
            }
        });
        //启动两个线程
        threadB.start();
        threadA.start();
    }
}

创建方式:通过Lock创建,Lock.newCondition();

常用方法:

await():阻塞,直到相同的Condition调用了signal方法。
signal():通知。

总结:Condition必须与Lock一起使用(wait()、notify()必须与synchronized一起使用,否则运行会报错java.lang.IllegalMonitorStateException),相比于wait与notify更加的灵活,可以设置各种情形,如上例中的到达3和到达6两个条件。

二,CountDownLatch

直接上代码:

public class CountDownLatchTest {
    public static void main(String[] args) {
        final CountDownLatch c = new CountDownLatch(3);//总数3
        Thread t1 = new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    System.out.println("开始等");
                    c.await();//阻塞,等待countDown,当countDown到0就执行后面的完事了
                    System.out.println("完事");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        });
        Thread t2 = new Thread(new Runnable(){
            @Override
            public void run() {
                for(int i=3;i>0;i--){
                    c.countDown();//减1
                }
            }

        });
        t1.start();
        t2.start();
    }}

创建方式:直接创建,new CountDownLatch(int num);

常用方法:

await():阻塞,直到countDown方法被执行了num次。
countDown():减

总结:适用于一个线程等待其他线程的情景。

三,CyclicBarrier

通过代码思考一下与CountDownLatch的区别。

public class MainMission {
    private CyclicBarrier barrier;
    private final static int threadCounts = 5;
    public void runMission() {
        ExecutorService exec=Executors.newFixedThreadPool(threadCounts);
        //new 的时候要传入数字,我发现,这个类似semaphore,如果位置不足,线程会抢位置。数字要是threadCounts+1为主线程留一个位子,但实际测试中发现,只要等于threadCount就可以
         barrier=new CyclicBarrier(threadCounts+1);
        for(int i=0;i<5;i++){
            exec.execute(new Mission(barrier));
        }
        try {
            barrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("所有任务都执行完了");
        exec.shutdown();//如果不关闭,程序一直处于运行状态
    }
    public static void main(String[] args) {
        MainMission m = new MainMission();
        m.runMission();
    }
}
class Mission implements Runnable{
    private CyclicBarrier barrier;
    public Mission(CyclicBarrier barrier){
        this.barrier = barrier;
    }
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"开始执行任务");
        try {
            int sleepSecond = new Random().nextInt(10)*1000;
            System.out.println(Thread.currentThread().getName()+"要执行"+sleepSecond+"秒任务");
            Thread.sleep(sleepSecond);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        try {
            barrier.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"执行完毕");
    }
}

创建方式:直接创建,new CyclicBarrier(int num);

常用方法:

await():阻塞,直到阻塞的线程数量达到num个。

总结:想想一下百米跑,所有运动员都就位之后才会发令起跑,线程调用await意味着说,我准备好了。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #0080e1 }
span.s1 { text-decoration: underline }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco }

原文地址:https://www.cnblogs.com/coolgame/p/8746750.html

时间: 2024-08-06 04:31:56

Java基础知识-java.util.concurrent包下常见类的使用的相关文章

java.util.concurrent包下的几个常用类

1.Callable<V> Callable<V>与Runnable类似,理解Callable<V>可以从比较其与Runnable的区别开始: 1)从使用上:实现的Callable<V>的类需要实现call()方法,此方法有返回对象V:而Runnable的子类需要实现run()方法,但没有返回值: 2)如果直接调用Callable<V>的子类的call()方法,代码是同步顺序执行的:而Runnable的子类是线程,是代码异步执行. 3)将Call

JAVA基础知识-java文化基础和运行环境

JAVA基础知识 1,java是95年sun公司推出的开发语言,发展很快,09年被oracle公司收购.至今分为SE.ME.EE三个发展方向和软件版本. 2,运行java的环境主要是通过JVM(java virtual machine)实现的.首先编写.java结尾的源文件,通过编译器编译成.class结尾的字节码文件,然后通过解释器实现在不同平台上一致运行的效果. 3,jvm,jre和jdk的区别:jvm,java虚拟机:jre,java运行环境,jdk:java开发工具包. 4,jdk的下载

java基础知识(10)---包

包:定义包用package关键字. 1:对类文件进行分类管理. 2:给类文件提供多层名称空间. 如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中即可. 一般在定义包名时,因为包的出现是为了区分重名的类.所以包名要尽量唯一.怎么保证唯一性呢?可以使用url域名来进行包名称的定义. package pack;//定义了一个包,名称为pack. 注意:包名的写法规范:所有字母都小写. //package cn.itcast.pack.demo;

java基础知识--java集合框架

java集合框架 1.概述: 集合框架被设计成要满足以下几个目标. 该框架必须是高性能的.基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的. 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性. 对一个集合的扩展和适应必须是简单的. 整个集合框架就围绕一组标准接口而设计.你可以直接使用这些接口的标准实现,诸如: LinkedList, HashSet, 和 TreeSet等,除此之外你也可以通过这些接口实现自己的集合. 集合框架是一个用来代表和操纵集合的统一架构.所有的集合

concurrent包下常用的类

转自 http://www.importnew.com/21889.html 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法. 以下是本文目录大纲: 一.CountDownLatch用法 二.CyclicBarrier用法 三.Semaphore用法 一.CountDownLatch用法 CountDownLatch类位于java.util.concu

带你玩转java多线程系列 “道篇” 多线程的优势及利用util.concurrent包测试单核多核下多线程的效率

java多线程 “道篇” - 多线程的优势及用concurrent包测试单核多核下多线程的效率 1 超哥对于多线程自己的理解 2 测试代码 3 CountDownLatch这个同步辅助类科普 4 如何把电脑设置成单核 5 测试结果 1 超哥对于多线程自己的理解 超哥的理解:对于多线程,无非是对于顺序执行下任务的一种抽取和封装,将原来顺序执行的任务单独拿出来放到线程类的run方法中,通过线程类的start方法进行执行,对于多线程访问共同资源时,我们需要加锁,也就是只有某个线程在拥有锁的时候,才能够

java基础知识回顾之java Thread类学习(把)--java.util.concurrent.locks(JDK1.5)与synchronized异同讲解

看API文档介绍几个方法:  JDK1.5中提供了多线程的升级解决方案: 特点: 1.将同步synchronized显示的替换成Lock                    2.接口Condition:Condition替代了Object监视器方法(wait.notify.notifyAll),分别替换成了await(),signal() (唤醒一个等待线               程),signalAll() 唤醒多个线程.一个锁可以绑定多个condition对象,可以对应好几组wait,

《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecut

java架构 [Java 基础] 使用java.util.zip包压缩和解压缩文件

Java API中的import java.util.zip.*;包下包含了Java对于压缩文件的所有相关操作. 我们可以使用该包中的方法,结合IO中的相关知识,进行文件的压缩和解压缩相关操作. ZipFile java中的每一个压缩文件都是可以使用ZipFile来进行表示的. File file = new File("F:/zippath.zip"); ZipFile zipFile = new ZipFile(file); System.out.println("压缩文