Java并发工具包- java.util.concurrent

  1. (队列)阻塞队列 BlockingQueue
    一个线程往里边放,另外一个线程从里边取的一个 BlockingQueue
    BlockingQueue是一个接口常用实现类为:
    *ArrayBlockingQueue:内存连续,查询快
    *LinkedBlockingQueue:内存不连续,添加方便
    实现类的各种操作:
    操作原则:FIFO先进先出
    初始化ArrayBlockingQueue:
    BlockingQueue queue = new ArrayBlockingQueue(理论上是有界的但是可以设置为Integer.MaxValue);
    初始化LinkedBlockingDeque:
    BlockingQueue queue=new LinkedBlockingDeque();Linked队列,默认的容量上限是Integer.MaxValue
    *具有优先级的阻塞队列PriorityBlockingQueue:
    优先级队列可以实现排序。队列的内部工作原理:按照compareto的排序规则对元素重新进行了排列,然后FIFO的原则来取的
    以传入Student对象为例:
    BlockingQueue queue=new PriorityBlockingQueue ();
    Student声明:
    public class Student implements Comparable,Cloneable
    public int compareTo(Student o) {
    return o.score-this.score;
    }

  2. (Map)并发 Map( 映射) ConcurrentMap
    HashMap 线程不安全
    HashTable 线程安全,底层实现的方式是所有的方法都加了同步代码块。但是问题是性能特别低
    HashTable会锁住整表,当有一线程操作HashTalble,其他线程即不能读,也不能写
    ConcurrentMap的实现原理:引入了分段锁(桶)的概念,分成了16个桶(segments).
    这样,当线程在操作某一个key的时候,锁住的是这个key对应的桶。理论上来说,ConcurrentMap的性能是HashTable的16倍
    定义:ConcurrentHashMap map=new ConcurrentHashMap();

  3. (Map)并发导航ConcurrentNavigableMap
    实现自截取,反省类必须实现cloneable接口,并重写其方法
    ConcurrentNavigableMap map=new ConcurrentSkipListMap();
    ConcurrentNavigableMap headMap=map.headMap(3);
    System.out.println(headMap.entrySet().size());//数字为2;
    headMap(T toKey) 方法返回一个包含了小于给定 toKey 的 key 的子 map。
    tailMap(T fromKey) 方法返回一个包含了不小于给定 fromKey 的 key 的子 map。
    subMap() 方法返回原始 map 中,键介于 from(包含) 和 to (不包含) 之间的子 map。

  4. (线程锁)闭锁 CountDownLatch
    闭锁(也叫线程递减锁)
    知识点1:创建闭锁时,需要赋值一个初始计数量。
    知识点2:await()会产生阻塞,当初始计数量=0时,阻塞放开
    知识点3:countDown()每调用一次,计数量-1
    主函数:
    CountDownLatch cdl=new CountDownLatch(2);
    new Thread(new GuoRunner(cdl)).start();
    new Thread(new CaiRunner(cdl)).start();
    cdl.await();
    执行函数:
    class GuoRunner implements Runnable{
    private CountDownLatch cdl;
    public GuoRunner(CountDownLatch cdl) {
    this.cdl=cdl;
    }
    public void run() {
    System.out.println(“锅买回来了”);
    cdl.countDown();//声明的计数减一
    }
    }

  5. (线程锁)栅栏 CyclicBarrier
    栅栏,可以实现线程同步效果。主要就是调用await()方法,将创建时赋值的初始计数器减为0.
    赛马例子:
    模拟两匹赛马(两个线程)
    只有当两匹赛马都到达栅栏前,比赛才开始
    主函数:
    CyclicBarrier cb=new CyclicBarrier(2);
    new Thread(new Horse1Runner(cb)).start();
    new Thread(new Horse2Runner(cb)).start();
    执行函数:
    try {
    //栅栏的await()方法会产生阻塞,此外,此方法被调用一次,初始计数器-1
    cb.await();
    }
    //栅栏的await()方法会产生阻塞,此外,此方法被调用一次,初始计数器-1,直至减到0,栅栏放开
    cb.await();

  6. (线程信息交换)交换机 Exchanger
    交换机:用于两个线程之间信息的交互,主要通过交换机的exchange方法来实现的。
    两个间谍传递暗号(两个线程)
    通过交换机相互传递暗号
    主函数:
    Exchanger ex=new Exchanger();
    new Thread(new Spy1(ex)).start();
    new Thread(new Spy2(ex)).start();
    执行函数:
    Object spy1Info=ex.exchange(info);//只能两个线程交换数据

  7. (线程类)Callable
    Callable类似于Runnable,一个类实现了Callable接口,就成为一个线程类
    1.Callable的call方法可以抛异常,Runnable的run方法不可以
    2.Callable的call方法可以有返回值,自己指定。run方法的返回值只能是void
    3.call方法的返回值是可以拿到的,应用场景:可以返回值来做具体判断,做相关的业务逻辑控制
    4.callable线程类只能通过线程池来启动。(不能通过new Thread().start()来启动)
    实例:
    ExecutorService es=Executors.newCachedThreadPool();
    Future future=es.submit(new CallRunner());
    System.out.println(“call方法的返回值:”+future.get());
    es.shutdown();

  8. (线程池)执行器服务 ExecutorService
    引入线程池,最重要的改善就是:避免线程的频繁创建和销毁
    第一个参数:corePoolSize:线程池的核心线程数量,此线程数量一直会创建,直到达到指定的数量位置
    第二个参数:maximumPoolSize:当核心线程和队列都满了之后,再有新的请求过来,会创建临时线程。
    原则是:核心线程数+临时线程数<=MaxPoolSize
    第三个参数: keepAliveTime:这个参数控制的是临时线程的存活时间(闲置时间),时间一过,临时线程被清理掉
    unit:时间单位
    第四个参数:workqueue:当核心线程都占用之后,再有新的请求过来,会将请求先存放到队列里等待出来。处理的原则是:FIFO
    第五个参数:拒绝服务器助手:当核心满+队列满+临时满的时候,再有新的请求过来,这个请求会转给线程池的拒绝服务器助手
    ExecutorService es=new ThreadPoolExecutor(
    5, 10, 3000,TimeUnit.MILLISECONDS,new ArrayBlockingQueue(5),new RejectedExecutionHandler() {
    //rejectedExecution 方法用于解决处理不了的请求
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    System.out.println(“服务器繁忙”);
    }});
    启动线程:
    es.execute(new ExRunner());
    大池子小队列newCachedThreadPool:

    • (0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,new SynchronousQueue())
      *特点:没有核心线程|临时线程无限|临时线程数量存活时间:60分钟|同步队列,队列里只能存储一个元素
      *大池子小队列:好处是响应时间短,能够快速和良好的处理请求。能够充分利用cpu。
      *隐患:如果请求数量大,而且都是长请求的话,可能会导致池子一直在创建新的线程,严重的后果会造成内存溢出。
      *适用场景:高访问量且短请求场景
      小池子大队列newFixedThreadPool:
    • nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new
      LinkedBlockingQueue()
    • 特点:只有核心线程|没有临时线程|因为没有临时线程,所以没有存活时间|队列是无界的
    • 小池子大队列:应用场景:能够缓解服务器压力,将处理不了的请求存到队列里,供后续处理。
    • 局限性:响应时间可能达不到立即响应。
  9. (锁) Java Lock 实现
    重入锁默认用的是非公平锁策略,非公平锁的吞吐量要高于公平锁的吞吐量
    重入锁潜在的风险:锁释放的问题,必须在finally代码块里做释放
    sychronized的锁释放是jvm来做的
    主函数:
    //重入锁,如果是true 是公平锁策略
    //默认是flase,非公平锁
    ReentrantLock lock=new ReentrantLock();
    new Thread(new Lock1Runner(lock)).start();
    new Thread(new Lock2Runner(lock)).start();
    执行函数:
    lock.lock();
    if(TestLock.name.equals(“李雷”)){
    TestLock.name=”韩梅梅”;
    TestLock.gender=”女”;
    }else{
    TestLock.name=”李雷”;
    TestLock.gender=”男”;
    }
    lock.unlock();//在finally代码块执行!
    读写锁:对锁实现细粒度的控制,能够达到只对写上锁,不影响读
    lock.writeLock().lock();
    lock.readLock().lock();
    finally {
    rwlock.writeLock().unlock();
    }
    finally {
    rwlock.readLock().unlock();
    }

  10. (元素类型)原子性布尔 AtomicBoolean
    原子性类型能够实现原子操作,底层的实现原理是加锁,这个数字在进行数学计算时,会被锁,从而实现数据不会被错误的覆盖。
    主函数:
    public static AtomicInteger i=new AtomicInteger(0);
    CountDownLatch cdl=new CountDownLatch(2);
    new Thread(new AtomicRunner(cdl)).start();
    new Thread(new AtomicRunner(cdl)).start();
    cdl.await();
    System.out.println(i);
    执行函数:
    for(int j=0;j<1000;j++){
    TestAtomic.i.addAndGet(1);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值