美文网首页
Java 多线程——工具包

Java 多线程——工具包

作者: BitterOutsider | 来源:发表于2020-11-29 20:36 被阅读0次

JUC

首先来说说synchronized的有什么缺点。

  • 它非常的死板。要么获取锁,要么等待锁,而且我们无法知晓此时这个锁有没有被人拿到,也不知道某个线程是否是上锁状态。
  • 只有悲观锁、排他锁,没有乐观锁、共享锁。有些资源允许很多线程去读,但是只允许一个线程写,这样的锁叫做共享锁。悲观锁就是做某个操作必须要拿到一个锁。乐观锁就是先去把一个任务做完,但由于多个线程竞争这个操作没有正确完成,那就重新做一遍,直到正确为止。
  • 性能相对较差

java.util.concurrent简称JUC,是Java的并发工具包,解决了上述的一些问题。

Lock / Condition

  • Lock提供了一个更加复杂的锁机制。它允许更加灵活的结构,支持不同的方法,支持相关的Condition操作。
    • 同一个锁可以有多个条件。
    • 读写分离。Lock的实现中有读锁WriteLock和写锁ReadLock
    • tryLock方法。如果该锁可用立刻返回true,不可用则立刻返回false
    • 可以方便的实现更加灵活的优先级/公平性。公平性指的是,假如有多个线程竞争一个锁的话,我以什么顺序给它们。非公平锁,主要靠操作系统的调度。Lock的实现中有可重入锁ReentrantLock(默认是非公平锁,可以传一个参数让它变成公平锁)。
  • ConditonObjectmonitor方法(waitnotifynotifyAll)拆出来成了独立的对象,使得支持多个等待集合。

CountDownLatch

  • 倒数闭锁。
  • 用于协调一组线程的工作。
  • 它的API简单暴力countDown()await()。以下是一个使用例子:
public class Main {
    public static void main(String[] args) throws InterruptedException {
        final CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(() -> {
                int second = new Random().nextInt(10);
                try {
                    Thread.sleep(second * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + finalI + "干完活了");
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("老板发话了,所有人干完活了!");
    }
}

CyclicBarrier

  • 循环的屏障
  • 等所有线程执行完了,才继续:
public class Main {
    public static void main(String[] args) throws InterruptedException {
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
        for (int i = 0; i < 5; i++) {
            int finalI = i;
            new Thread(() -> {
                int second = new Random().nextInt(10);
                try {
                    Thread.sleep(second * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程" + finalI + "干完活了");

                try {
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }

                System.out.println("所有线程都执行完了,大家一起说!");

            }).start();
        }
    }
}

Semaphore

  • 信号量
  • 信号量的获取和释放

BlockingQueue & BlockingDeque

  • 传统的集合框架的操作要么正常返回,要么丢出异常,BlockingQueue/BlockingDeque提供⼀种「等待」的可能。
  • API: 阻塞操作:put/take
  • 先声明容量大小,如果put超过容量,则会等待另一个线程take
  • BlockingQueue先进先出。BlockingDeque头尾都能进出,更加灵活。

Future & ExecutorService

  • Future代表⼀个「未来才会发⽣的事情」。
    • Future本身是⽴即返回的。
    • get()会阻塞并返回执⾏结果,并抛出可能的异常。异常的抛出一般只会在当前线程,而get可以把其他线程的异常转移到当前线程抛出。
  • 线程池的参数。建议看ExecutorService的一个实现:ThreadPoolExecutor文档。
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default rejected execution handler.
     *
-----* 核心线程的数量,哪怕它们闲下来,也不会被丢弃。
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
-----* 最多可以开这么多的线程工作。
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        poo
-----* 下面两个是联合使用的,非核心线程空闲多久会被杀死。
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
-----* 保存那些还没被执行的任务。
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
-----* 每当你需要一个新的线程的时候,用它来创建。
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
-----* 假如任务来的太快,把任务队列撑满了,要采取何种策略?
-----* AbortPolicy丢弃策略、CallerRunsPolicy让调用者执行
-----* DiscardOldestPolicy丢弃最老的一个任务、DiscardOldestPolicy丢弃最新的一个任务。
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
  • 还可以举一个通俗易懂的例子,假如你是一个老板,有如下的参数解释:

    • corePoolSize 核⼼员⼯数量
    • maximumPoolSize 最⼤招募的员⼯数量
    • keepAliveTime/unit 员⼯闲下来多久之后炒掉他们
    • workQueue 订单队列
    • threadFactory 造⼈的⼯⼚
    • handler 订单实在太多的处理策略
  • Java 默认实现的线程池,使用Executors.xxx创建一个线程池,且这些方法大多都返回一个ThreadPoolExecutor,如下所示:

public static ExecutorService newxxxThreadPool(xxx) {
    return new ThreadPoolExecutor(六个参数);
}

相关文章

  • JUC指什么?

    JUC是java.util.concurrent并发工具包的简称,是JDK1.5新增处理java多线程并发的工具包

  • Java并发编程从基础到进阶

    从Java多线程基础到Java内存模型;从synchronized关键字到Java并发工具包JUC。 我们不生产知...

  • Java 多线程——工具包

    JUC 首先来说说synchronized的有什么缺点。 它非常的死板。要么获取锁,要么等待锁,而且我们无法知晓此...

  • JVM,JRE,JDK的关系及jvm内存模型

    JDK(Java Development Kit,Java开发工具包) -包含了Java的开发工具包括JRE-用于...

  • 带你搞懂Java多线程(五)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二)带你搞懂Java多线程(三)带你搞懂Java多线程(四) ...

  • 带你搞懂Java多线程(六)

    带你搞懂Java多线程(一)带你搞懂Java多线程(二)带你搞懂Java多线程(三)带你搞懂Java多线程(四)带...

  • Java多线程目录

    Java多线程目录 Java多线程1 线程基础Java多线程2 多个线程之间共享数据Java多线程3 原子性操作类...

  • Java 8并发工具包漫游指南

    Java 8并发工具包简介 Java 8并发工具包由3个包组成,分别是java.util.concurrent、j...

  • javaSE学习-JDK和JRE

    JDK:java开发工具包,程序员在开发java程序的时候会用到的工具包。 JRE(Java Runtime En...

  • Java并发工具包——CyclicBarrier

    Java并发工具包——CyclicBarrier 回顾 上一期Java并发工具包跟大家聊了下CountDownLa...

网友评论

      本文标题:Java 多线程——工具包

      本文链接:https://www.haomeiwen.com/subject/rnucwktx.html