首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【Java多线程】JUC其他常用组件

【Java多线程】JUC其他常用组件

作者头像
用户11935701
发布2025-12-16 08:55:45
发布2025-12-16 08:55:45
100
举报

Callable

我们知道在JAVA的线程中我们只能执行任务,而这个任务不能返回一个值,而Callable的出现就是为了弥补这一缺陷。

Callable:定义一个带有返回值的任务, 并没有真的在执行,需要搭配Thread对象来使用。

Thread本身不提供获取结果的方法,需要凭FurureTask对象来得到结果,这么做是为了解耦合。

代码语言:javascript
复制
public static void main(String[] args) throws ExecutionException, InterruptedException {
    Callable<Integer> callable = new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            Integer res = 0;
            for (int i = 0; i < 10; i++) {
                res += i;
            }
            return res;
        }
    };
    FutureTask<Integer> futureTask = new FutureTask<>(callable);
    Thread thread = new Thread(futureTask);
    thread.start();
    System.out.println(futureTask.get());
}
代码语言:javascript
复制
//匿名写法
FutureTask<Integer> futureTask = new FutureTask<>(()->{
    Integer res = 0;
    for (int i = 0; i < 10; i++) {
        res += i;
    }
    return res;
});

get方法用于获取FutureTask的返回值,如果FutureTask没有运行完成get方法会产生阻塞,直到线程运行完毕,get拿到返回结果。

ReentrantLock (可重入锁)

通过lock()和unlock()方法加解锁,效率比synchronized低,远古时期用的较多。

如果要使用ReentrantLock进行加锁,可以通过此方式防止忘记解锁

代码语言:javascript
复制
locker.lock();
try {
	//代码逻辑
} finally {
	locker.unlock();
}

ReentrantLock和synchronized的区别:

  1. synchronized 是 关键字(内部实现是 JVM 内部通过 C++ 实现的),ReentrantLock 标准库的类(Java)。
  2. synchronized 通过代码块控制加锁解锁,ReentrantLock 需要 lock/unlock 方法,需要注意 unlock 不被调用的问题。
  3. ReentrantLock 除了提供 lock, unlock 之外,还提供了一个方法trylock(),这个方法不会产生阻塞,加锁成功返回true,失败返回false,可以由调用者决定接下来怎么做。
  4. ReentrantLock提供了公平锁的实现,默认是非公平,需要在创建的时候传入true。
  5. ReentrantLock搭配的等待通知机制是Condition类,相比于wait notify来说要更加强大灵活一些。

semaphore(信号量)

信号量表示的是“可用资源的个数”,申请一个资源,计数器就会+1,释放一个就会-1,如果为0,继续申请就会陷入阻塞等待。

代码语言:javascript
复制
//设置初始数量
Semaphore semaphore = new Semaphore(5);
//申请一个资源
semaphore.acquire();
//获取多少个资源可以申请
System.out.println(semaphore.availablePermits());
//释放一个资源
semaphore.release();
System.out.println(semaphore.availablePermits());

作用:

  1. 限制同时访问某资源的线程数(如接口限流、数据库连接池)。
  2. 管理有限的资源(如线程池、数据库连接池)。

特殊场景: 当初始值为1时,等价于“锁”。

代码语言:javascript
复制
Semaphore mutex = new Semaphore(1);  // 二进制信号量

void criticalSection() throws InterruptedException {
    mutex.acquire();
    try {
        // 临界区代码(同一时间仅一个线程可进入)
    } finally {
        mutex.release();
    }
}

CountDownLatch

在使用多线程,经常把一个大任务拆分成多个子任务,可以提高程序的效率。

那么我们如何判定这个大任务已经完成了呢?Java引入了CountDownLatch类帮助我们判定。

  1. 在构造时传入参数,表示有多少个任务。
  2. 在每个任务完成时,调用一次countDown方法,当次数足够时,说明任务已经全部完成。
  3. 在主线程中调用await方法会等待任务全部完成。
代码语言:javascript
复制
public static void main(String[] args) throws InterruptedException {
    CountDownLatch countDownLatch = new CountDownLatch(10);
    //重写工厂类方法
    ThreadFactory threadFactory = new ThreadFactory() {
        private int cnt = 0;
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, "Thread" + cnt);
            thread.setDaemon(true);
            return thread;
        }
    };
    //使用工厂类创建线程池
    ExecutorService executorService = Executors.newFixedThreadPool(1, threadFactory);
    //提交任务
    for (int i = 0; i < 10; i++) {
        int id = i;
        executorService.submit(()->{
            System.out.println("开始" + Thread.currentThread().getName() + id);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("结束" + Thread.currentThread().getName() + id);
            countDownLatch.countDown();
        });
    }
    //等待全部完成
    countDownLatch.await();
    System.out.println("全部结束了");
}

感谢各位的观看Thanks♪(・ω・)ノ,如果觉得满意的话留个关注再走吧。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Callable
  • ReentrantLock (可重入锁)
  • semaphore(信号量)
  • CountDownLatch
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档