常用的几个JUC工具类

CountDownLatch

CountDownLatch初始化的时候给定一个计数,每次调用countDown计数减一

当计数未到达0之前调用await方法阻塞,直到计数减到0

使用场景,多用于划分任务由多个线程执行,例如,我们要写一个爬虫,需要爬取每个电影的前五页短评,可以划分五个线程来处理数据,通过latch.swait保证全部完成在返回

public class CountDownLatch {
    public void latch() throws InterruptedException {
        int count= 5;
        java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(count);
        for (int x=0;x<count;x++){
            new Worker(x*20,latch).start();
        }
        latch.await();
        System.out.println("全部执行完毕");
    }
    class Worker extends Thread{
        Integer start;
        java.util.concurrent.CountDownLatch latch;
        public Worker(Integer start, java.util.concurrent.CountDownLatch latch){
            this.start=start;
            this.latch=latch;
        }

        @Override
        public void run() {
            System.out.println(start+" 已执行");
            latch.countDown();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch();
        countDownLatch.latch();
    }

}

CyclicBarrier

允许一组线程相互等待,知道到达某个公共屏障点(common barrier point)也就是阻塞在调用cyclicBarrier.await的地方,看上去和CountDownlatch功能上类似,CountDownLatch的计数无法被重置,如果需要被重置,请考虑使用CyclicBarrier

CyclicBarrier初始化时还可以添加一个Runnable的参数,此Runnable在CyclicBarrier的数目达到后,所有其他线程被唤醒前被最后一个进入CyclicBarrier的线程执行
使用场景:类似CountDownLatc,但是CyclicBarrier提供几个CountDownBarrier没有的方法以来应付更加复杂的场景,例如:getNumberWaiting() 获取阻塞线程数量,
isBroken() 用来知道阻塞的线程是否被中断等方法。
reset() 将屏障重置为其初始状态。如果所有参与者目前都在屏障处等待,则它们将返回,同时抛出一个 BrokenBarrierException。

Semaphore

Semaphore 信号量维护了一个许可集,每次使用时执行acquire()从Semaphore获取许可,如果没有则会阻塞,每次使用完执行release()释放许可。

使用场景:Semaphore对用于对资源的控制,比如数据连接有限,使用Semaphore限制访问数据库的线程数。

package JUC;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * projectName:test
 * name:SemaphoreTest
 * description:todo
 * date:2020/5/12 10:48 下午
 * auther:AlexNi
 */
public class SemaphoreTest {
    public void latch() throws InterruptedException, IOException {
        int count = 5;
        Semaphore semaphore = new Semaphore(1);
        ExecutorService executorService = Executors.newFixedThreadPool(count);
        for (int x=0;x<count;x++){
            executorService.execute(new Worker(x,semaphore));
        }
        System.in.read();
    }

    class Worker extends Thread {
        Integer start;
        Semaphore semaphore;

        public Worker(Integer start, Semaphore semaphore) {
            this.start = start;
            this.semaphore = semaphore;
        }

        @Override
        public void run() throws IllegalArgumentException {
            try {
                System.out.println(start + " 准备执行");
                TimeUnit.SECONDS.sleep(1);
                semaphore.acquire();
                System.out.println(start + " 已经执行");
                semaphore.release();
                System.out.println(start + " 已经释放");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        SemaphoreTest test = new SemaphoreTest();
        test.latch();
    }
}

Exchanger

Exchanger 用于两个线程间的数据交换,它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。

使用场景: 两个线程相互等待处理结果并进行数据传递。

package JUC;

import java.io.IOException;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * projectName:test
 * name:Exchanger
 * description:todo
 * date:2020/5/12 11:05 下午
 * auther:AlexNi
 */
public class ExchangerTest {
    public void latch() throws InterruptedException, IOException {
        int count = 5;
        Exchanger<String> exchanger = new Exchanger<>();
        ExecutorService executorService = Executors.newFixedThreadPool(count);
        for (int x=0;x<count;x++){
            executorService.execute(new Worker(x,exchanger));
        }
        System.in.read();
    }

    class Worker extends Thread {
        Integer start;
        Exchanger<String>  exchanger;

        public Worker(Integer start, Exchanger<String> exchanger) {
            this.start = start;
            this.exchanger = exchanger;
        }

        @Override
        public void run() throws IllegalArgumentException {
            try {
                System.out.println(Thread.currentThread().getName() + " 准备执行");
                TimeUnit.SECONDS.sleep(start);
                System.out.println(Thread.currentThread().getName() + " 等待交换");
                String value = exchanger.exchange(Thread.currentThread().getName());
                System.out.println(Thread.currentThread().getName() + " 交换得到数据为:"+value);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {
        ExchangerTest test = new ExchangerTest();
        test.latch();
    }
}

Exchanger必须成对出现,否则会像上面代码执行结果那样,pool-1-thread-5一直阻塞等待与其交换数据的线程,为了避免这一现象,可以使用exchange(V x, long timeout, TimeUnit unit)设置最大等待时长

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的JUCjava.util.concurrent)包提供了一些并发编程常用的类,这些类可以帮助我们更方便地实现多线程编程。以下是一些常用JUC类及其解析: 1. CountDownLatch(倒计时器) CountDownLatch是一个计数器,它允许一个或多个线程等待一组事件发生后再继续执行。它最基本的方法是await()和countDown()。await()方法会阻塞当前线程,直到计数器的值为0;countDown()方法会将计数器的值减1。 2. CyclicBarrier(循环屏障) CyclicBarrier是一个同步工具,它允许一组线程等待彼此达到一个公共屏障点。当所有线程都到达这个屏障点时,它们才能继续执行。CyclicBarrier可以被重复使用,当所有线程都执行完后,它会自动重置。 3. Semaphore(信号量) Semaphore是一种计数器,它维护了一组许可证。当调用acquire()方法时,线程会阻塞,直到许可证可用;而当调用release()方法时,许可证的数量会增加。Semaphore可以用于限制同时访问某些资源的线程数量。 4. ReentrantLock(重入锁) ReentrantLock是一个可重入的互斥锁。它和synchronized关键字类似,但是提供了更多的灵活性和功能。ReentrantLock中最常用的方法是lock()和unlock(),它们分别用于获取锁和释放锁。 5. ConcurrentHashMap(并发哈希表) ConcurrentHashMap是一个线程安全的哈希表实现。它和HashMap类似,但是支持并发访问。ConcurrentHashMap中的所有方法都是线程安全的,而且它的性能比Hashtable和同步的HashMap要好。 6. Executors(线程池) Executors是一个工厂类,用于创建各种类型的线程池。它提供了一些静态方法,例如newFixedThreadPool()、newCachedThreadPool()、newSingleThreadExecutor()等,可以方便地创建各种类型的线程池。 7. Future(异步计算) Future是一个接口,它表示一个异步计算的结果。Future可以通过get()方法获取计算结果,或者通过cancel()方法取消计算。Future还可以用于实现一些高级的并发操作,例如等待一组异步计算全部完成后再继续执行。 总的来说,JUC包提供了很多有用的类和工具,可以帮助我们更方便地实现多线程编程,提高程序的并发性能和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值