博客
关于我
第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/

    你可能感兴趣的文章
    Objective-C实现FermatPrimalityTest费马素数测试算法(附完整源码)
    查看>>
    Objective-C实现fft2函数功能(附完整源码)
    查看>>
    Objective-C实现FFT快速傅立叶变换算法(附完整源码)
    查看>>
    Objective-C实现FFT算法(附完整源码)
    查看>>
    Objective-C实现fibonacci search斐波那契查找算法(附完整源码)
    查看>>
    Objective-C实现fibonacci斐波那契算法(附完整源码)
    查看>>
    Objective-C实现fibonacci斐波那契算法(附完整源码)
    查看>>
    Objective-C实现FIFO(附完整源码)
    查看>>
    Objective-C实现FigurateNumber垛积数算法(附完整源码)
    查看>>
    Objective-C实现finding bridges寻找桥梁算法(附完整源码)
    查看>>
    Objective-C实现first come first served先到先得算法(附完整源码)
    查看>>
    Objective-C实现fischer yates shuffle洗牌算法(附完整源码)
    查看>>
    Objective-C实现fisherYates洗牌算法(附完整源码)
    查看>>
    Objective-C实现frequency finder频率探测器算法(附完整源码)
    查看>>
    Objective-C实现FTP文件上传(附完整源码)
    查看>>
    Objective-C实现fuzzy operations模糊运算算法(附完整源码)
    查看>>
    Objective-C实现Gale-Shapley盖尔-沙普利算法(附完整源码)
    查看>>
    Objective-C实现gamma recursive伽玛递归算法(附完整源码)
    查看>>
    Objective-C实现gauss easte高斯复活节日期算法(附完整源码)
    查看>>
    Objective-C实现gaussian filter高斯滤波器算法(附完整源码)
    查看>>