1、PriorityBlockingQueue里面存储的对象必须是实现Comparable接口。

2、队列通过这个接口的compare方法确定对象的优先级priority。

规则是:当前和其他对象比较,如果compare方法返回负数,那么在队列里面的优先级就比较高

下面的测试可以说明这个断言:

查看打印结果,比较take出来的Entity和left的entity,比较他们的priority

public class TestPriorityQueue { 

static Random r=new Random(47); 

public static void main(String args[]){ 

final PriorityBlockingQueue q = new PriorityBlockingQueue(); 

ExecutorService se = Executors.newCachedThreadPool();

final int qTime = r.nextInt(100);
//execute producer
se.execute(new Runnable(){
public void run() {
int i=0;
while(true){
q.put(new PriorityEntity(r.nextInt(10), i++)); //优先级,索引
try {
TimeUnit.MILLISECONDS.sleep(qTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}); //execute consumer
se.execute(new Runnable(){
public void run() {
while(true){
try {
int rTime = r.nextInt(500); //打印进队和出队的时间可以看到队列一直在累积
System.out.println(qTime + ": " rTime + " --take-- "+q.take()+" left: "+q.size()+" -- ["+q.toString()+"]");
try {
TimeUnit.MILLISECONDS.sleep(rTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}); //try {
// TimeUnit.SECONDS.sleep(5);
//} catch (InterruptedException e) {
// e.printStackTrace();
//}
System.out.println("shutdown");
} } class PriorityEntity implements Comparable<PriorityEntity> { private int priority;
private int index=0; public PriorityEntity(int _priority,int _index) {
this.priority = _priority;
this.index=_index;
} public String toString(){
return "# [index="+index+" priority="+priority+"]";
} //数字小,优先级高
public int compareTo(PriorityEntity o) {
return this.priority > o.priority ? 1 : this.priority < o.priority ? -1 : 0;
} //数字大,优先级高
// public int compareTo(PriorityTask o) {
// return this.priority < o.priority ? 1 : this.priority > o.priority ? -1 : 0;
// }
}

理解 newCachedThreadPool()

1、创建线程池的根源:

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)

2、使用场景:
2.1、耗时较短的任务。
2.2、任务处理速度 > 任务提交速度 ,这样才能保证不会不断创建新的进程,避免内存被占满。newCachedThreadPool可以看成newFixedThreadPool(无穷大),虽然无法限制线程总数,但是可以减少不必要的线程创建和销毁上的消耗,

3、取名为cached-threadpool的原因在于线程池中的线程是被线程池缓存了的,也就是说,线程没有任务要执行时,便处于空闲状态,处于空闲状态的线程并不会被立即销毁(会被缓存住),只有当空闲时间超出一段时间(默认为60s)后,线程池才会销毁该线程(相当于清除过时的缓存)。新任务到达后,线程池首先会让被缓存住的线程(空闲状态)去执行任务,如果没有可用线程(无空闲线程),便会创建新的线程。

4、

看一段测试代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class newCachedThreadPoolTest {
public static void main(String[] args) {
  ExecutorService executorService = Executors.newCachedThreadPool();
  for (int i = 1; i < 10000; i++)
  executorService.submit(new task());
  }
  }   class task implements Runnable {
  @Override
  public void run() {
  try {
  Thread.sleep(5000);
  } catch (InterruptedException e) {
  e.printStackTrace();
    }
  }
}

运行结果为:Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

可以看出来是堆外内存溢出,因为我们新建的线程都在工作(代码中用sleep表示在工作中),newCachedThreadPool 只会重用空闲并且可用的线程,所以上述代码只能不停地创建新线程,在 64-bit JDK 1.7 中 -Xss 默认是 1024k,也就是 1M,那就是需要 10000*1M = 10G 的堆外内存空间来给线程使用,但是我的机器总共就 8G 内存,不够创建新的线程,所以就 OOM 了。

所以这个newCachedThreadPool 大家一般不用就是这样的原因,因为它的最大值是在初始化的时候设置为Integer.MAX_VALUE,一般来说机器都没那么大内存给它不断使用。当然知道可能出问题的点,就可以去重写一个方法限制一下这个最大值,但是出于后期维护原因,一般来说用 newFixedThreadPool 也就足够了。

Java如何依据cpu核数设置合适的线程数

newFixedThreadPool 定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()获取cpu核心数。

executorservice pool = executors.newfixedthreadpool(runtime.getruntime().availableprocessors()*10);一般建议每cpu不超过25个线程,当然多一点也没什么问题,不过就费点线程资源.

java.lang.Runtime.availableProcessors() 方法返回到Java虚拟机的可用的处理器数量。此值可能会改变在一个特定的虚拟机调用。应用程序可用处理器的数量是敏感的,因此偶尔查询该属性,并适当地调整自己的资源使用情况.

PriorityBlockingQueue 和 Executors.newCachedThreadPool()的更多相关文章

  1. 线程池(3)Executors.newCachedThreadPool

    例子: ExecutorService es = Executors.newCachedThreadPool(); try { for (int i = 0; i < 20; i++) { Ru ...

  2. java 多线程:线程池的使用Executors~ExecutorService; newCachedThreadPool;newFixedThreadPool(int threadNum);ScheduledExecutorService

    1,为什么要使用线程池:Executors 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更 ...

  3. Java并发之BlockingQueue 阻塞队列(ArrayBlockingQueue、LinkedBlockingQueue、DelayQueue、PriorityBlockingQueue、SynchronousQueue)

    package com.thread.test.thread; import java.util.Random; import java.util.concurrent.*; /** * Create ...

  4. Java四种线程池newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? Java new Thread(new Runnable() { @Override public void ru ...

  5. Java多线程之新类库中的构件PriorityBlockingQueue

    package concurrent2; import java.util.ArrayList; import java.util.List; import java.util.Queue; impo ...

  6. Executors常用的创建ExecutorService的几个方法说明

    一.线程池的创建 我们可以通过ThreadPoolExecutor来创建一个线程池. new ThreadPoolExecutor(corePoolSize, maximumPoolSize, kee ...

  7. java PriorityBlockingQueue 基于优先级队列,的读出操作可以阻止.

    java PriorityBlockingQueue 基于优先级队列.的读出操作可以阻止. package org.rui.thread.newc; import java.util.ArrayLis ...

  8. Java线程池实现原理与技术(ThreadPoolExecutor、Executors)

    本文将通过实现一个简易的线程池理解线程池的原理,以及介绍JDK中自带的线程池ThreadPoolExecutor和Executor框架. 1.无限制线程的缺陷 多线程的软件设计方法确实可以最大限度地发 ...

  9. Java线程池ThreadPoolExecutor&&Executors

    一.先看看传统的开启线程. new Thread(new Runnable() { @Override public void run() { } }).start(); 缺点: 1.每次new Th ...

随机推荐

  1. 值得收藏的js原型详解

    从虚无到Object 起初,地是空虚混沌,渊面黑暗:这时候一切还是null 神说,要有原型,于是就有了prototype 原型从凭空产生,于是需要一个指向于null的特征,人们把这种特征叫做隐式原型, ...

  2. PDF怎么转换成Word,免费,完整的那种

      简介 PDF可以分为文字型PDF和图片型PDF,文字型PDF即可以选中文字内容的PDF,反之图片型PDF即无法选中文字的PDF,其内容实际上是图片. 本文针对不同类型,介绍PDF转Word方法,可 ...

  3. Algorithms - Quicksort - 快速排序算法

    相关概念 快速排序法 Quicksort 也是一个分治思想的算法. 对一个子数组 A[p: r] 进行快速排序的三步分治过程: 1, 分解. 将数组 A[p : r] 被划分为两个子数组(可能为空) ...

  4. python语法学习第六天--字典

    字典:可变容器类型,用键值对的形式采用花括号储存(键唯一) 语法:d={key1:value1,key2:value2} 访问字典中的值: 字典名[键名]#若字典中不存在则报错 更改字典: 添加值:字 ...

  5. [hdu4710 Balls Rearrangement]分段统计

    题意:求∑|i%a-i%b|,0≤i<n 思路:复杂度分析比较重要,不细想还真不知道这样一段段跳还真的挺快的=.= 令p=lcm(a,b),那么p就是|i%a-i%b|的循环节.考虑计算n的答案 ...

  6. Jmeter-函数助手之${__RandomString(,,)}使用

    ${__RandomString(,,)}使用方法 1.在日常写脚本中,可以随机生成指定的几个字符串作为入参的value,那么jmeter 的这个工具就特别好用.  应用: 2.填写接口入参, 3.运 ...

  7. SpringBatch异常To use the default BatchConfigurer the context must contain no more thanone DataSource

    SpringBoot整合SpringBatch项目,已将代码开源至github,访问地址:https://github.com/cmlbeliever/SpringBatch 欢迎star or fo ...

  8. 什么是virtual string tree?

    Virtual stringtree(以后简称VST)是一个提供源码的免费的第三方插件,支持DELPHI和C++builder,可在http://www.soft-gems.net/下载到最新的版本. ...

  9. java 多线程详细笔记(原理理解到全部使用)

    鸽了好久以后终于又更新了,看同学去实习都是先学源码然后修改之类,才发觉只是知道语法怎么用还远远不够,必须要深入理解以后不管是学习还是工作,才能举一反三,快速掌握. 目录 基础知识 进程与线程 线程原子 ...

  10. SpringBoot注解分析

    Spring boot 简介:是spring社区发布的一个开源项目,旨在帮助开发者更快更简单的构建项目,使用习惯优于配置,的理念让你的项目快速的跑起来,使用springboot可以不用,或者很少的配置 ...