美文网首页
java 线程池使用

java 线程池使用

作者: Theodore的技术站 | 来源:发表于2019-04-19 18:29 被阅读0次

java Executors 类提供了四种线程池,分别为:
newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }

newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

SynchronousQueue

SynchronousQueue 是无界的,是一种无缓冲的等待队列,但是由于该 Queue 本身的特性,在某次添加元素后必须等待其他线程取走后才能继续添加;

可以认为 SynchronousQueue 是一个缓存值为 1 的阻塞队列,但是 isEmpty()方法永远返回是true,remainingCapacity() 方法永远返回是 0,remove() 和 removeAll() 方法永远返回是 false,iterator() 方法永远返回空,peek() 方法永远返回null。

声明一个 SynchronousQueue 有两种不同的方式,它们之间有着不太一样的行为。公平模式和非公平模式的区别:如果采用公平模式:SynchronousQueue 会采用公平锁,并配合一个FIFO队列来阻塞多余的生产者和消费者,从而体系整体的公平策略;

但如果是非公平模式(SynchronousQueue 默认):SynchronousQueue 采用非公平锁,同时配合一个LIFO队列来管理多余的生产者和消费者,而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理。

LinkedBlockingQueue

LinkedBlockingQueue 是无界的,是一个无界缓存的等待队列。
基于链表的阻塞队列,内部维持着一个数据缓冲队列(该队列由链表构成)。

当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue 可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。

LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

DelayedWorkQueue

DelayedWorkQueue 是无界的优先级队列。用数组储存数据,元素个数超过数组长度,就会调用grow()方法,进行数组扩容。

内部用对实现优先级队列,将新元素添加到优先级队列中对应的位置,通过siftUp方法,保证按照元素的优先级排序。

如果新插入的元素是队列头,即更换了队列头,那么就要唤醒正在等待获取任务的线程。这些线程可能是因为原队列头元素的延时时间没到,而等待的。

保证添加到队列中的任务,会按照任务的延时时间进行排序,延时时间少的任务首先被获取。

使用示例:

newCachedThreadPool:

package Demo;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
public class ThreadPoolExecutorTest {  
 public static void main(String[] args) {  
  ExecutorService cachedThreadPool = Executors.newCachedThreadPool();  
  for (int i = 0; i < 10; i++) {  
   final int index = i;  
   try {  
    Thread.sleep(index * 1000);  
   } catch (InterruptedException e) {  
    e.printStackTrace();  
   }  
   cachedThreadPool.execute(new Runnable() {  
    public void run() {  
     System.out.println(index);  
    }  
   });  
  }  
 }  
}  

newFixedThreadPool

package Demo;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
public class ThreadPoolExecutorTest {  
 public static void main(String[] args) {  
  ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);  
  for (int i = 0; i < 10; i++) {  
   final int index = i;  
   fixedThreadPool.execute(new Runnable() {  
    public void run() {  
     try {  
      System.out.println(index);  
      Thread.sleep(5000);  
     } catch (InterruptedException e) {  
      e.printStackTrace();  
     }  
    }  
   });  
  }  
 }  
}  

newScheduledThreadPool

package Demo;  
import java.util.concurrent.Executors;  
import java.util.concurrent.ScheduledExecutorService;  
import java.util.concurrent.TimeUnit;  
public class ThreadPoolExecutorTest {  
 public static void main(String[] args) {  
  ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);  
  scheduledThreadPool.schedule(new Runnable() {  
   public void run() {  
    System.out.println("delay 3 seconds");  
   }  
  }, 3, TimeUnit.SECONDS);  
 }  
}  

newSingleThreadExecutor

package Demo;  
import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
public class ThreadPoolExecutorTest {  
 public static void main(String[] args) {  
  ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();  
  for (int i = 0; i < 10; i++) {  
   final int index = i;  
   singleThreadExecutor.execute(new Runnable() {  
    public void run() {  
     try {  
      System.out.println(index);  
      Thread.sleep(5000);  
     } catch (InterruptedException e) {  
      e.printStackTrace();  
     }  
    }  
   });  
  }  
 }  
}  

相关文章

  • 线程

    Java 并发编程:线程池的使用 Java 并发编程:线程池的使用java 多线程核心技术梳理 (附源码) 本文对...

  • Java线程池解析

    参考文章:Java并发:线程池,饱和策略 前言 Java线程池的使用在工作中还是比较常见的,线程池可以减小线程建立...

  • 零碎知识点整理

    sofa结构体系:多模块 sofa中使用sofa线程池 Java 线程池的使用非常广泛,目前有两类广泛使用的线程池...

  • 线程池

    线程池 原创 无尘粉笔 粉笔社区 昨天 Java线程池的Executors的使用 Java通过Executors提...

  • Java/Android中的线程池,看这一篇就够了!(超详细)

    一、为何要使用线程池 在Java中,要使用多线程,除了使用new Thread()之外,还可以使用线程池Execu...

  • springboot线程池创建及使用

    springboot启动类(Application.java)中配置线程池大小 使用类中注入线程池并使用

  • Java并发编程:线程池的使用

    Java并发编程:线程池的使用

  • Java 线程池

    Java线程池是java cocurrent包下提供的类,使用非常方便。本文希望整理下Java 线程池相关的知识以...

  • java 线程池

    java 线程池 Java 的 concurrent 包下提供了多种线程池的实现,使用起来非常方便 Executo...

  • Java线程池总结

    本篇文章讲述Java中的线程池问题,同样适用于Android中的线程池使用。本篇文章参考:Java线程池分析,Ja...

网友评论

      本文标题:java 线程池使用

      本文链接:https://www.haomeiwen.com/subject/thycgqtx.html