JavaEE 第15节 JUC相关组件介绍

目录

前言:

Callable 

ReentrantLock

Semaphore

CountDownLatch


前言:

在Java中,JUC(包路径:java.util.concurrent)是一个用于并发编程的包,提供了线程安全的集合类、同步工具、并发执行框架和原子变量等,以简化和增强多线程编程的性能和可靠性。接下来介绍的这几个组件使用起来都比较简单。


Callable 

Callable是一个接口,你可以理解成它是一个带有返回值的Runnable。

如图,Runnable和Callable的创建对比:

Thread类没有关于Callable的构造方法。原因在于需要通过Callable的实例创建FutureTask的实例才行:

public class CallableTest {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
   

        Callable<Integer> callable=new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println("hehhe");
                return 10;
            }
        };

        /**在创建线程的时候,多出了创建FutureTask的对象这一步*/
        FutureTask<Integer> futureTask=new FutureTask<>(callable);

        Thread thread=new Thread(futureTask);
        thread.start();
        thread.join();

        /*get方法可以获取到返回值*/
        int ret=futureTask.get();
        System.out.println("thread:"+ret);
    }
}

FutureTask是一个类,它的get方法可以获取call方法的返回值。

执行结果:

hehhe
thread:10


ReentrantLock

除了synchronized,Java标准库开提供了其他方式对线程进行加锁的操作。

比如:Excuters(第10节线程池讲过)、Semaphore(等一下会讲)、ReentrantLock(当前正题)等。

ReentrantLock是一个类(需要创建对象使用),与synchronized对比,ReentrantLock的区别:

  • 加锁方式:需要用到lock()/unlock()来上锁解锁,因此为了避免死锁,最好把unlock()放到finally块中。
  • tryLock:ReentrantLock提供了tryLock(),调用此方法,如果加锁失败,当前线程不会进入阻塞状态,而是直接返回,执行别的任务。
  • 公平锁:ReentrantLock默认是不公平锁,不过可以在使用构造方法的时候设置成公平锁。
  • 更精确的通知:ReentrantLock实现了Condition接口,在这个接口中,提供了一组方法,可以精确的唤醒某个满足特定条件的线程。而synchronized只能随机或全部唤醒。

Semaphore

Semaphore是计算机的一个专业术语,意为“信号量”。

它是一个控制资源访问的同步类工具。它可以限制同时访问某一个特定资源的总线程数量,保证多个线程可以有序的访问共享资源。

举个形象的例子:

在停车场的入口,我们通常会看到这个显示剩余车位的指示牌:

Semaphore就可以类比成这个指示牌。用了这个指示牌,外面的车子就不会无脑的开进去,在车位满了的时候就不会出现拥堵。

Semaphore的使用方式:

public class SemaphoreTest {

    public static void main(String[] args) {
        Semaphore semaphore=new Semaphore(4);
        
        for (int i = 0; i <20 ; i++) {
            int id=i;
            Thread t=new Thread(()->{
                try {
                    System.out.println("申请资源");
                    semaphore.acquire();//申请资源的方法
                    System.out.println("执行任务:"+id);
                    System.out.println("释放资源");
                    semaphore.release();//释放资源的方法

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            t.start();
        }
    }
}

如果Semaphore构造方法的参数设置成1,那么它就变成了一个加锁操作,一个线程在完成了任务后,其他线程才可以继续执行。

CountDownLatch

CountDownLatch是JUC中的一个同步辅助类,用它的构造方法可以设置一个任务数量,每次执行完一个任务,可以调用它自带的contDown()方法任务计数器会-1。当任务计数器为0的时候,可以唤醒其他线程(调用了CountDownLatch类的'await()'方法的线程,这个方法可以让调用它的线程进入睡眠直到任务计数器减为0)。

代码演示:

public class JUCcountDown {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService service= Executors.newFixedThreadPool(4);
        CountDownLatch latch=new CountDownLatch(20);

        for (int i = 0; i <20 ; i++) {
            int id=i;
            service.submit(()->{
                System.out.println("执行任务:"+id);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("任务:"+id+"执行完毕");
                latch.countDown();//计数器-1
            });
        }

        //主线程进入睡眠,计数器为0才会苏醒
        latch.await();

        System.out.println("所有任务执行完毕!");
    }
}

  • 23
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值