博客
关于我
第45天学习打卡(Set 不安全 Map不安全 Callable 常用的辅助类 读写锁 阻塞队列 线程池)
阅读量:140 次
发布时间:2019-02-28

本文共 4779 字,大约阅读时间需要 15 分钟。

Java并发编程入门

1. Set 不安全性

使用普通的Set时可能存在不安全性,需要采取额外措施确保线程安全。常见的解决方法包括:

  • 使用Collections.synchronizedSet包装普通Set。
  • 使用CopyOnWriteArraySet,这是一种线程安全的Set实现。
  • Set
    set = Collections.synchronizedSet(new HashSet<>());// 或者Set
    set = new CopyOnWriteArraySet<>();

    2. HashSet 和 Map 的底层实现

    HashSet内部实际上使用HashMap来存储元素。其主要方法包括:

    public boolean add(E e) {    return map.put(e, PRESENT) == null;}

    这里的PRESENT是一个固定常量,用于表示元素已存在。

    Map的基本操作虽然简单,但在多线程环境下可能引发ConcurrentModificationException,需要谨慎使用。

    3. Callable

    Callable类提供了与Runnable类似的方法,但可以有返回值和抛出异常。主要方法包括:

    public interface Callable
    { V call() throws Exception;}

    与Runnable不同,Callable可以通过FutureTask等类来执行,并可以有返回值。例如:

    FutureTask
    futureTask = new FutureTask<>(new MyThread());new Thread(futureTask, "A").start();Integer result = futureTask.get();

    4. CountDownLatch

    CountDownLatch是一个计数器,用于等待一组任务完成。常见用法包括:

    CountDownLatch countDownLatch = new CountDownLatch(6);for (int i = 1; i <= 6; i++) {    new Thread(() -> {        System.out.println(Thread.currentThread().getName() + "Go out");        countDownLatch.countDown();    }, String.valueOf(i)).start();}countDownLatch.await();System.out.println("Close Door");

    CountDownLatch的核心原理是通过countDown方法减少计数器数量,await方法等待计数器归零。

    5. CyclicBarrier

    CyclicBarrier是一个循环屏障,常用于多个线程协同完成任务。例如:

    CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {    System.out.println("召唤神龙成功!");});for (int i = 1; i <= 7; i++) {    new Thread(() -> {        System.out.println(Thread.currentThread().getName() + "搜集" + i + "个龙珠");        try {            cyclicBarrier.await();        } catch (InterruptedException | BrokenBarrierException e) {            e.printStackTrace();        }    }).start();}

    CyclicBarrier的await方法会等待所有参与线程完成任务后才继续。

    6. Semaphore

    Semaphore是一个信号量,用于控制资源的使用和线程的互斥。常见用法包括:

    Semaphore semaphore = new Semaphore(3);for (int i = 1; i <= 6; i++) {    new Thread(() -> {        try {            semaphore.acquire();            System.out.println(Thread.currentThread().getName() + "抢到车位");            TimeUnit.SECONDS.sleep(2);            System.out.println(Thread.currentThread().getName() + "离开车位");        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            semaphore.release();        }    }, String.valueOf(i)).start();}

    Semaphore的acquire方法获取信号量,release方法释放信号量。

    7. ReadWriteLock

    ReadWriteLock提供了读锁和写锁,允许多个线程同时持有读锁,但只能一个线程持有写锁。常见用法包括:

    ReadWriteLock readWriteLock = new ReadWriteLock();for (int i = 1; i <= 5; i++) {    new Thread(() -> {        myCache.put(temp + "", temp);    }, String.valueOf(i)).start();}for (int i = 1; i <= 5; i++) {    new Thread(() -> {        myCache.get(temp + "");    }, String.valueOf(i)).start();}

    ReadWriteLock的写锁是独占锁,而读锁是共享锁。

    8. BlockingQueue

    BlockingQueue是一种阻塞队列,支持线程安全的生产和消费。常见实现包括ArrayBlockingQueue和SynchronousQueue。ArrayBlockingQueue有固定容量,会阻塞生产和消费操作;SynchronousQueue没有容量限制,生产和消费操作都需要等待。

    ArrayBlockingQueue
    blockingQueue = new ArrayBlockingQueue<>(3);blockingQueue.put("a");blockingQueue.put("b");blockingQueue.put("c");System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());

    9. SynchronousQueue

    SynchronousQueue是一个同步队列,put和take操作必须成对出现。例如:

    SynchronousQueue
    synchronousQueue = new SynchronousQueue<>();new Thread(() -> { try { System.out.println(Thread.currentThread().getName() + " put 1"); synchronousQueue.put("1"); System.out.println(Thread.currentThread().getName() + " put 2"); synchronousQueue.put("2"); System.out.println(Thread.currentThread().getName() + " put 3"); } catch (InterruptedException e) { e.printStackTrace(); }}, "T1").start();new Thread(() -> { try { TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + " > " + synchronousQueue.take()); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + " > " + synchronousQueue.take()); TimeUnit.SECONDS.sleep(3); System.out.println(Thread.currentThread().getName() + " > " + synchronousQueue.take()); } catch (InterruptedException e) { e.printStackTrace(); }}, "T2").start();

    10. 线程池(核心)

    线程池是资源池化的典范,通过ThreadPoolExecutor实现。线程池的三大方法包括:

    • newSingleThreadExecutor:单线程池。
    • newFixedThreadPool:固定线程池。
    • newCachedThreadPool:可扩展线程池。

    线程池的核心参数包括核心线程池大小、最大线程池大小、线程保持时间和工作队列类型。常见用法包括:

    ExecutorService threadPool = Executors.newSingleThreadExecutor();for (int i = 0; i < 100; i++) {    threadPool.execute(() -> {        System.out.println(Thread.currentThread().getName() + " ok");    });}threadPool.shutdown();

    线程池的四种拒绝策略包括:

    • AbortPolicy:默认策略,放入队列,执行时抛出RejectedExecutionException。
    • CallerRunsPolicy:直接在调用者线程上执行任务。
    • DiscardPolicy:丢弃任务,不抛出异常。
    • DiscardOldestPolicy:丢弃最旧的任务。

    线程池的核心优势在于优化资源利用率,降低资源消耗,提高响应速度。

    转载地址:http://ertd.baihongyu.com/

    你可能感兴趣的文章
    Python.对象集合中的标识.和散列
    查看>>
    Python.硒.拖放错误“AttributeError:move_to 需要 WebElement“
    查看>>
    Python内置函数详解
    查看>>
    Python/Kivy:从一个类调用函数到另一个类并在 Python 中显示小部件
    查看>>
    Python/Kivy:我可以在双击标签时调用函数吗
    查看>>
    python内置函数5-frozenset()
    查看>>
    Python/Plotly:如何使用要显示的信息自定义悬停模板?
    查看>>
    Python/Selenium - 无法单击 www.instagram.com 上的“接受 cookie“按钮
    查看>>
    Python内置函数(35)——next
    查看>>
    python写入mysql
    查看>>
    python写入csv老是乱码或者各种不好
    查看>>
    Python内置函数
    查看>>
    Python2 安装MySQLdb库
    查看>>
    Python2 已终结,入手Python 3,你需要这30个技巧
    查看>>
    python写下拉列表在excel,无法使用python获取Excel下拉列表(组合框)值
    查看>>
    python2.7安装
    查看>>
    Python2.7安装ncmbot时提示:Microsoft Visual C++9.0 is required
    查看>>
    PYTHON2.Git.1
    查看>>
    python20181211
    查看>>
    Python内存管理机制
    查看>>