温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

CountDownLatch和线程池怎么在java并发包中使用

发布时间:2021-02-18 13:51:17 来源:亿速云 阅读:232 作者:Leah 栏目:开发技术

今天就跟大家聊聊有关CountDownLatch和线程池怎么在java并发包中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

1.CountDownLatch

创建这样一个门栓

CountDownLatch countDownLatch = new CountDownLatch(count);

参数:count,门栓的计数次数。

在所有线程执行完成之前,调用countDownLatch.await()阻塞主线程。

每当一个线程执行完一个指定动作之后,count就会减少1,当count等于0时,主线程不再阻塞,开始继续执行下面的代码,当count大于0时,主线程一直阻塞,等待count变为0。每个线程动作执行结束后,执行countDownLatch.countDown(),这个门栓的count减一。

int ThreadNum = 16;
CountDownLatch countDownLatch = new CountDownLatch(ThreadNum);
for(int i = 0; i < ThreadNum ; i++){
 final int finalI = i;
 new Thread(() -> {
  int n = 0;
  System.out.println("线程应该做的事情");
  while(n < 10){
   n++;
  }
  countDownLatch.countDown();
 }).start();
}
try{
 countDownLatch.await();
}catch(InterruptedException e){
 logger.infor("InterruptedException!!");
}

2.线程池

其实线程池之前的ipv6的项目里用过,但是也忘记得差不多了,复习一下。

线程在创建和关闭时都需要花费时间,如果为每一个小的任务都创建一个线程,可能创建和销毁线程所用的时间会多于该线程真实工作所消耗的时间,就会得不偿失。除了时间,空间也需要考虑,线程本身也是要占用内存空间的,大量的线程会食用过多的内存资源,可能会造成OOM。另外在回收时,大量的线程会延长GC的停顿时间。

因此在生产环境中使用线程必须对其加以控制和管理

使用线程池之后,创建线程变成了从线程池中获得空闲的线程,关闭线程变成了归还线程给线程池。

通过ThreadPoolExecutor可以创建一个线程池,ThreadPoolExecutor实现了Executors接口。

举个栗子:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolTest {
 public static void main(String[] args) {
  ThreadPoolExecutor pool = new ThreadPoolExecutor(10,20,60, 
    TimeUnit.SECOUNDS,new ArrayBlockingQueue<Runnable>(15000),new ThreadFactory(){
   private AtomicInteger threadId = new AtomicInteger(0);
   @Override
   public Thread newThread(Runnable r){
    Thread thread = new Thread(r);
    thread.setDaemon(true);
    String prefix = "thread-";
    thread.setName(prefix+threadId.incrementAndGet());
    return thread;
   } 
  });
 }
}

这样就创建了一个线程池。参数依次解释:

corePoolSize:指定了线程池中线程的数量,线程池中可以有10个存活的线程

maximumPoolSize:指定了线程池中最大的线程数,线程池中最多能有20个存活的线程

keepAliveTime:当线程池中的数量超过corePoolSize时,这些线程在多长时间会被销毁,60s

unit:keepAliveTime的单位

workQueue:任务队列,被提交但是没有被执行的任务存在的地方。他是一个BlockingQueue<Runnable>接口的对象。

threadFactory:线程工厂,你想创建什么样子的线程

重点说一下workQueue:

根据队列的功能分类,可以使用以下几种BlockingQueue接口

补充:Java中CountDownLatch,CyclicBarrier以及Semaphore的使用场景

Java并发包中提供了很多有用的工具类来帮助开发者进行并发编程,今天我就来说说CountDownLatch,CyclicBarrier以及Semaphore这三个的用法和使用场景。

1.CountDownLatch使用场景和用法

CountDownLatch一般是用于某个线程等待其他线程执行完之后,它才能执行。例如一家人在等待爸爸妈妈回家,才能进行晚宴,示例代码如下:

public class CountDownLatchTest {
 
 public static void main(String[] args) throws Exception {
  final CountDownLatch cdl = new CountDownLatch(2);
  new Thread(){
   public void run() {
    try {
     System.out.println("等待老爸回家...");
     Thread.sleep(5000);
     cdl.countDown();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    
   };
  }.start();
  
  new Thread(){
   public void run() {
    try {
     System.out.println("等待老妈回家...");
     Thread.sleep(5000);
     cdl.countDown();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   };
  }.start();
  
  cdl.await();
  System.out.println("老爸老妈回来了...");
  System.out.println("晚宴开始了...");
 }
 
}

2.CyclicBarrier(栅栏)使用场景和用法

CyclicBarrier一般是一组线程等待至某个状态,然后这一组线程才能同时执行(感觉跟CountDownLatch有点类似啊,不过仔细想想还是有差别的,感觉容易混淆)。

代码示例如下:

public class CyclicBarrierTest {
 
 public static void main(String[] args) {
  int count = 3;
  CyclicBarrier cb = new CyclicBarrier(count, new Runnable() {
   @Override
   public void run() {
    //此处所有线程都调用了await方法之后,会走到这里
    System.out.println("所有线程操作完成之后都调用了await方法");
   }
  });
  
  for(int i=0;i<count;i++){
   new WriteLogHandler(cb).start();
  }
 }
 
 static class WriteLogHandler extends Thread{
  
  private CyclicBarrier cb = null;
  
  public WriteLogHandler(CyclicBarrier cb) {
   this.cb = cb;
  }
  
  @Override
  public void run() {
   try {
    System.out.println("线程:" + Thread.currentThread().getName() + "开始写日志");
    Thread.sleep(2000);
    System.out.println("线程:" + Thread.currentThread().getName() + "写日志结束,等待其他线程");
    cb.await();
    
    System.out.println("所有线程写日志数据结束,继续其他操作");
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
 }
 
}

3.Semaphore(信号量)使用场景和用法

Semaphore类似锁的用法,用于控制对某资源的访问权限,示例代码如下:
public class SemaphoreTest {
 
 public static void main(String[] args) {
  ExecutorService executor = Executors.newCachedThreadPool();
  final Semaphore semaphore = new Semaphore(5);
  
  for(int i=0;i<10;i++){
   final int num = i;
   executor.execute(new Runnable() {
    @Override
    public void run() {
     try {
      semaphore.acquire();
      System.out.println("正在执行任务" + num);
      Thread.sleep((long)Math.random() * 1000);
      System.out.println("任务" + num + "执行结束");
      semaphore.release();
     } catch (Exception e) {
      e.printStackTrace();
     }
    }
   });
  }
  executor.shutdown();
 }
 
}

看完上述内容,你们对CountDownLatch和线程池怎么在java并发包中使用有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI