Java JUC概述

news/2024/5/20 7:53:19 标签: java, juc, java并发

Java JUC(Java Util Concurrent)是 Java 平台提供的并发编程工具包,它提供了一系列的工具类和接口,用于简化多线程编程。JUC 中的类和接口都是基于 Java 平台的底层并发原语(如锁、信号量、原子变量等)实现的,可以帮助开发者更加方便和安全地完成多线程编程。

JUC 中的常用类和接口

1. Lock 和 ReentrantLock

Lock 接口是 Java 并发包中提供的一种比 synchronized 更加灵活的锁机制。它提供了更加细粒度的控制,可以实现更加复杂的线程同步操作。ReentrantLock 是 Lock 接口的一个实现类,它提供了与 synchronized 相同的互斥性和内存可见性,同时还提供了更多的高级功能,如可重入锁、公平锁等。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {
    private Lock lock = new ReentrantLock();

    public void print() {
        lock.lock();
        try {
            // 线程安全的代码
            System.out.println(Thread.currentThread().getName() + " is running");
        } finally {
            lock.unlock();
        }
    }
}

2. Condition

Condition 接口是 Lock 接口提供的一个高级功能,它可以用于实现线程之间的通信。一个 Condition 对象可以和一个 Lock 对象关联,当一个线程调用 Condition 的 await() 方法时,它会释放掉与这个 Condition 对象关联的 Lock 对象的锁,并进入等待状态;当另一个线程调用 Condition 的 signal() 或 signalAll() 方法时,它会通知一个或所有正在等待的线程恢复执行。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionDemo {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private int count = 0;

    public void produce() {
        lock.lock();
        try {
            while (count >= 10) {
                condition.await();
            }
            count++;
            System.out.println(Thread.currentThread().getName() + " produce, count = " + count);
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void consume() {
        lock.lock();
        try {
            while (count <= 0) {
                condition.await();
            }
            count--;
            System.out.println(Thread.currentThread().getName() + " consume, count = " + count);
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

3. Semaphore

Semaphore 是一种计数信号量,它可以用于控制同时访问某个资源的线程数量。Semaphore 维护了一个计数器,每当一个线程访问该资源时,计数器就会减一;当计数器为零时,所有试图访问该资源的线程都会被阻塞,直到计数器大于零。

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    private Semaphore semaphore = new Semaphore(5);

    public void access() {
        try {
            semaphore.acquire();
            // 线程安全的代码
            System.out.println(Thread.currentThread().getName() + " is running");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
    }
}

4. CountDownLatch

CountDownLatch 是一种同步工具类,它可以让一个或多个线程等待其他线程完成操作后再继续执行。CountDownLatch 维护了一个计数器,线程调用它的 await() 方法会阻塞,直到计数器变为零;而其他线程完成操作后,可以调用 CountDownLatch 的 countDown() 方法将计数器减一。

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    private CountDownLatch countDownLatch = new CountDownLatch(3);

    public void task() {
        try {
            // 模拟耗时操作
            Thread.sleep((long) (Math.random() * 1000));
            System.out.println(Thread.currentThread().getName() + " is running");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            countDownLatch.countDown();
        }
    }

    public void start() {
        for (int i = 0; i < 3; i++) {
            new Thread(this::task).start();
        }
        try {
            countDownLatch.await();
            System.out.println("All tasks have been completed");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

5. CyclicBarrier

CyclicBarrier 是一种同步工具类,它可以让一组线程在达到某个共同点之前相互等待。CyclicBarrier 维护了一个计数器和一个栅栏点,每当一个线程到达栅栏点时,计数器就会减一;当计数器为零时,所有线程就可以继续执行。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    private CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
        System.out.println("All threads have arrived at the barrier");
    });

    public void task() {
        try {
            // 模拟耗时操作
            Thread.sleep((long) (Math.random() * 1000));
            System.out.println(Thread.currentThread().getName() + " has arrived at the barrier");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName() + " is running");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        for (int i = 0; i < 3; i++) {
            new Thread(this::task).start();
        }
    }
}

JUC 中的常用工具类

1. Executors

Executors 是一个工具类,用于创建线程池。它提供了一些静态方法,可以方便地创建不同类型的线程池。常用的方法有:

  • newFixedThreadPool(int nThreads):创建一个固定大小的线程池,该线程池中的线程数始终为 nThreads。
  • newCachedThreadPool():创建一个缓存线程池,该线程池可以根据需要创建新的线程,但在有可用线程时重用旧线程。
  • newSingleThreadExecutor():创建一个单线程池,该线程池中始终只有一个线程在工作。
  • newScheduledThreadPool(int corePoolSize):创建一个定时任务线程池,该线程池可以在指定的延迟时间后执行任务,也可以按照固定的时间间隔执行任务。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorsDemo {
    private ExecutorService executorService = Executors.newFixedThreadPool(5);

    public void execute() {
        executorService.execute(() -> {
            // 线程安全的代码
            System.out.println(Thread.currentThread().getName() + " is running");
        });
    }

    public void shutdown() {
        executorService.shutdown();
    }
}

2. Future 和 FutureTask

Future 接口表示一个异步计算的结果,它提供了一些方法,可以查询计算是否完成、等待计算完成并获取结果。FutureTask 是 Future 接口的一个实现类,它可以用于异步执行任务,并且可以在任务执行完成后获取任务的执行结果。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureTaskDemo {
    private FutureTask<Integer> futureTask = new FutureTask<>(() -> {
        // 模拟耗时操作
        Thread.sleep((long) (Math.random() * 1000));
        return 1;
    });

    public void start() {
        new Thread(futureTask).start();
    }

    public void get() {
        try {
            int result = futureTask.get();
            System.out.println("Result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

3. ConcurrentHashMap

ConcurrentHashMap 是一个线程安全的哈希表,它可以在高并发的情况下提供更好的性能。它的实现原理是将整个哈希表分成多个段,每个段都是一个独立的哈希表,可以独立地进行添加、删除、修改等操作。这样,当多个线程同时访问不同的段时,就可以实现真正的并行操作,从而提高了并发性能。

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapDemo {
    private ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    public void put(String key, int value) {
        map.put(key, value);
    }

    public int get(String key) {
        return map.get(key);
    }
}

JUC 中的高级特性

1. AQS

AQS(AbstractQueuedSynchronizer)是 JUC 中的一个重要类,它提供了一种通用的同步框架,可以用于实现各种同步器,如锁、信号量、倒计时门栓等。AQS 的核心思想是基于一个先进先出(FIFO)的队列,来管理等待获取同步状态的线程。当一个线程获取同步状态失败时,它会被封装成一个节点,然后加入到等待队列中,等待其他线程释放同步状态后再次尝试获取。

2. ForkJoin

ForkJoin 框架是 JUC 中的一个高性能并行计算框架,它可以将一个大任务拆分成多个小任务,并行地执行这些小任务,最后将小任务的结果合并成大任务的结果。ForkJoin 框架的核心思想是“工作窃取”,即当一个线程的任务执行完毕后,它可以从其他线程的任务队列中窃取一个任务来执行,以此来实现负载均衡。

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class ForkJoinDemo extends RecursiveTask<Integer> {
    private int start;
    private int end;

    public ForkJoinDemo(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        if (end - start <= 100) {
            int sum = 0;
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else {
            int mid = (start + end) / 2;
            ForkJoinDemo left = new ForkJoinDemo(start, mid);
            ForkJoinDemo right = new ForkJoinDemo(mid + 1, end);
            left.fork();
            right.fork();
            return left.join() + right.join();
        }
    }

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinDemo task = new ForkJoinDemo(1, 1000);
        Integer result = forkJoinPool.invoke(task);
        System.out.println("Result: " + result);
    }
}

总结

Java JUC 提供了一系列的工具类和接口,用于简化多线程编程。在实际开发中,我们应该根据具体的业务需求选择合适的工具类和接口,以提高程序的并发性能和可靠性。同时,我们还应该遵守多线程编程的最佳实践,如避免死锁、竞态条件等问题,以确保程序的正确性和稳定性。

公众号请关注"果酱桑", 一起学习,一起进步!


http://www.niftyadmin.cn/n/450877.html

相关文章

二进制文件和文本文件的存储大小的区别及计算方式

二进制文件和文本文件的存储过程是不一样的。 一般来说&#xff0c;二进制文件要小于文本文件的。 二进制文件存储 二进制文件存储不用符号什么的隔开&#xff0c;直接数与数紧挨在一起。比如10&#xff0c; 12的存储需要4个字节。存10的时候&#xff0c;二进制编码是0Ah, 00…

青少年和成人错误监测神经源的多模态研究

导读 儿童和成人对目标导向行为的监控能力不同&#xff0c;这可以通过几种任务和技术来测量。此外&#xff0c;最近的研究表明&#xff0c;错误监测的个体差异在调节焦虑情绪的倾向方面具有重要作用&#xff0c;而且这种调节作用会随着年龄的增长而变化。本研究使用多模态方法…

这届年轻人“吃翻”东南亚榴莲

【潮汐商业评论/原创】 “不少人说今年买榴莲堪比炒期货&#xff0c;我算是体会到了。”Andy如是说。 “4月前半月买&#xff0c;23.9/斤&#xff0c;4月后半月买&#xff0c;26.9/斤&#xff0c;5月前半月买&#xff0c;29.9/斤&#xff0c;5月后半月买&#xff0c;39.9/斤。…

【玩转Docker小鲸鱼叭】虚拟化技术简介

什么是虚拟化技术&#xff1f; Docker 是一款基于容器虚拟化技术构建的软件&#xff0c;那到底什么虚拟化技术呢&#xff1f;在学习 Docker 之前&#xff0c;先简单了解下虚拟化技术。 虚拟化是云原生的实现基础&#xff0c;它能够帮助我们更加有效地利用物理计算机硬件。 虚…

Three.js教程:Canvas画布布局和全屏

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 其他系列工具&#xff1a; NSDT简石数字孪生 Canvas画布布局和全屏 threejs渲染输出的结果就是一个Cavnas画布&#xff0c;canvas画布也是HTML的元素之一&#xff0c;这意味着three.js渲染结果的布局和普通web前端习惯是一…

C++ 设计模式----“对象创建“模式

“对象创建”模式  通过“对象创建” 模式绕开new&#xff0c;来避免对象创建&#xff08;new&#xff09;过程中所导致的紧耦合&#xff08;依赖具体类&#xff09;&#xff0c;从而支持对象创建的稳定。它是接口抽象之后的第一步工作。  典型模式 • Factory Method •…

基于人工智能的AI理发师能帮托尼老师做什么?

BarberGPT是一个人工智能理发师&#xff0c;它可以让您在照片上尝试不同的发型。您只需要上传您的照片&#xff0c;标记您的头发&#xff0c;然后就可以看到惊人的变化。BarberGPT使用了先进的深度学习技术&#xff0c;可以根据您的脸型、肤色和发质生成适合您的发型。BarberGP…

AI写作工具:让写作更高效,更便捷

随着人工智能技术的不断发展&#xff0c;现在已经有了一些AI写作工具&#xff0c;它们可以自动生成文章、提供编辑建议、规范语言格式&#xff0c;甚至表现出类似于人类写作的思考和创造力。通过小Q办公软件中的AI写作工具&#xff0c;不仅为写作人员带来了更高效的写作方式&am…