线程池

怎么找到部署在服务器上的应用的任务执行时所在线程?

newFixedThreadPool工厂方法将线程池的基本大小和最大大小设置为参数中指定的值,而且创建的线程池不会超时。newChchedThreadPool工厂方法将线程池的最大大小设置为Integer.MAX_VALUE,而将基本大小设置为0,并将超时设置为一分钟。这种方法创建出来的线程池可以无限扩展,并且当需求降低时可以自动收缩。其他形式的线程池可以通过显式的ThreadPoolExecutor构造函数来构造。

应用:(核心——Executors、ThreadPoolExecutor)

线程池的组成——1,线程池管理器:用于创建和管理线程

                            2.工作线程:线程池中线程

                            3.任务接口:每个任务必须实现的接口,以便工作线程调度任务的执行。

                            4.任务队列:用于存放没有处理的任务,提供一种缓冲机制。

 java中通过Executors类提供五种线程池:

http://blog.csdn.net/hsuxu/article/details/8985931

newCachedThreadPool

1.有任务时才创建新线程,空闲线程被保留60秒。corePoolSize为0,maximumPoolSize可以无限大

2.一个可缓存的线程池,线程池大小可根据处理需要来变大。可灵活回收空闲线程,若无可回收的则新建线程。如果执行第二个任务时第一个任务已完成,则会复用执行第一个任务的线程,不会新建。

newFixedThreadPool

一个大小固定的线程池,可控制线程最大并发数。超出的线程会在队列中等待,空闲的线程会一直保留。corePoolSize和maximumPoolSize的大小是一样的

newScheduledThreadPool

 按时间来执行任务或周期性的执行任务的线程池

newSingleThreadExecutor

只有一个工作线程,依次执行每个任务,可以给任务指定优先级

newSingleThreadScheduledExecutor

只有一个工作线程,按时间来执行任务 

 java中通过ThreadPoolExecutor类提供的线程池:

http://blog.csdn.net/zhouhl_cn/article/details/7392607

http://blog.sina.com.cn/s/blog_9b7d76e30102wlz8.html(第一类线程池的参数大小)

http://dongxuan.iteye.com/blog/901689(线程池中队列选择)

参数解释:

核心线程数及设置:核心线程会一直存活,即使没有任务需要处理。当线程数小于核心线程数时,即使现有的线程空闲,线程池也会优先创建新线程来处理任务,而不是直接交给现有的线程处理。

每个任务需要tasktime秒处理,则每个线程每钞可处理1/tasktime个任务。系统每秒有tasks个任务需要处理,则需要的线程数为:tasks/(1/tasktime)

queueCapacity:任务队列容量。任务队列的容量会影响到线程的变化,因此任务队列的长度也需要恰当的设置。

(corePoolSize/tasktime)*responsetime(切记队列不要使用无界队列LinkedBlockingQueue)

responsetime指允许系统最大的响应时间

最大线程数设置:当线程数大于或等于核心线程,且任务队列已满时,线程池会创建新的线程,直到线程数量达到maxPoolSize。如果线程数已等于maxPoolSize,且任务队列已满,则已超出线程池的处理能力,线程池会拒绝处理任务而抛出异常。任务队列不满不会创建新线程喽?

(最大任务数-队列容量)/每个线程每秒处理能力 = 最大线程数

 每个线程每秒处理能力即每个任务花费时间

 KeepAliveTime:当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize。如果allowCoreThreadTimeout设置为true,则所有线程均会退出直到线程数量为0。线程空闲指的是线程的哪些状态? KeepAliveTime指的是执行完任务后的非核心线程的存活时间

keepAliveTime参数和timeUnit参数也是配合使用的。keepAliveTime参数指明等待时间的量化值,timeUnit指明量化值单位。例如keepAliveTime=1,timeUnit为TimeUnit.MINUTES,代表空闲线程的回收阀值为1分钟。

 一个任务通过ThreadPoolExecutor的实例调用 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是Runnable类型对象的run()方法。

 任务是一个线程对象,接受到的数据作为参数在创建线程对象时用其构造方法赋值给线程对象的属性。

代码样例:http://blog.chinaunix.net/uid-20577907-id-3519578.html

          http://blog.csdn.net/wangwenhui11/article/details/6760474

对于不同性质的任务来说,CPU密集型任务应配置尽可能小的线程,如配置CPU个数+1的线程数,IO密集型任务应配置尽可能多的线程,因为IO操作不占用CPU,不要让CPU闲下来,应加大线程数量,如配置两倍CPU个数+1,而对于混合型的任务,如果可以拆分,拆分成IO密集型和CPU密集型分别处理,前提是两者运行的时间是差不多的,如果处理时间相差很大,则没必要拆分了。

若任务对其他系统资源有依赖,如某个任务依赖数据库的连接返回的结果,这时候等待的时间越长,则CPU空闲的时间越长,那么线程数量应设置得越大,才能更好的利用CPU。 

http://www.cnblogs.com/ghost240/p/3863774.html

整理:

java提供了两种创建线程池的方式:Executors类和ThreadPoolExecutor类。

 Executors类提供了五个方法来创建线程池。。。。。。

ThreadPoolExecutor类。。。。。

无论使用Executors类的五个方法创建线程池还是直接创建ThreadPoolExecutor的实例,最后用的构造方法都是ThreadPoolExecutor类的七个参数的此方法:

public ThreadPoolExecutor(int paramInt1, int paramInt2, long paramLong, TimeUnit paramTimeUnit, BlockingQueue<Runnable> paramBlockingQueue, ThreadFactory paramThreadFactory, RejectedExecutionHandler paramRejectedExecutionHandler)
{
if ((paramInt1 < 0) || (paramInt2 <= 0) || (paramInt2 < paramInt1) || (paramLong < 0L))
throw new IllegalArgumentException();
if ((paramBlockingQueue == null) || (paramThreadFactory == null) || (paramRejectedExecutionHandler == null))
throw new NullPointerException();
this.corePoolSize = paramInt1;
this.maximumPoolSize = paramInt2;
this.workQueue = paramBlockingQueue;
this.keepAliveTime = paramTimeUnit.toNanos(paramLong);
this.threadFactory = paramThreadFactory;
this.handler = paramRejectedExecutionHandler;
}

这七个参数的意义是:

核心线程数,最大线程数,空闲线程的最大存活时间,时间单位

队列:通常使用ArrayBlockingQueue,使用LinkedBlockingQueue时不指定大小会默认为无界队列。

          排队有三种通用策略:直接提交:工作队列的默认选项是SynchronousQueue。SynchronousQueue是一个空了才能存入,存在才能取出的队列,只保留一个元素(任务)在队列里。它的需求场景是这样的:队列中当前的产品没有被消费掉则不能再接受生产者的产品。这样可以保证消费者和生产者的节奏一致。其它的队列有缓存的意思,消费者消费不了那么多的时候可以在队列中缓存一部分产品。这样不容易影响生产者的速度。

线程工厂:

控制器:提交任务书超过最大线程数和工作队列之和时,任务被handler来处理(服务器拒绝服务的策略逻辑)

设置线程池的大小:

线程池的理想大小取决于被提交任务的类型和所部署系统的特性。代码中通常不会固定线程池的大小,而应该通过某种配置机制来提供。或者根据Runtime.availableProcessors来动态计算。

要想正确地设置线程池的大小,必须分析计算环境,资源预算和任务的特性。在部署的系统中有多少个CPU,多大的内存,任务是计算密集型还是IO密集型。如果需要执行不同类别的任务,并且它们之间的行为相差很大,应该考虑使用多个线程池,从而使每个线程池可以根据各自的工作负载来调整。

对于计算密集型的任务,线程池的大小设置为处理器数+1时,通常能实现最优的利用率。对于包含io操作或其他阻塞操作的任务,由于线程并不会一定执行,因此线程池的规模应该更大。要正确的设置线程池的大小,你必须估算出任务的等待时间与计算时间的比值。这种估算不需要很精确,并且可以通过一些分析或监控工具来获得。也可以通过另一种办法,在某个基准负载下,分别设置不同大小的线程池来运行程序,并观察CPU利用率的水平。

Nc=numbers of CPU

Uc=target CPU utilization(0到1之间)

W/C=ratio of wait time of compute time  

要使处理器达到期望的使用率,线程池的最优大小等于:

N=Nc*Uc*(1+W/C)

当然,CPU周期并不是唯一影响线程池大小的资源,还包括内存,文件句柄,套接字句柄和数据库连接等。计算这些资源对线程池的条件更容器:计算每个任务对该资源的需求量,然后用该资源的可用总量除以每个任务的需求量,所得结果就是线程池大小的上限。

当任务需要某种通过资源池来管理的资源时,例如数据库连接,那么线程池和资源池的大小将会相互影响。如果每个任务都需要一个数据库连接,那么连接池的大小就限制了线程池的大小。同样,当线程池中的任务是数据库连接的唯一使用者时,那么线程池的大小又将限制连接池的大小。

                                                                                       CPU介绍

HZ指频率,每秒的周期数。

CPU的工作时间由三部分组成:用户态时间,系统态时间,空闲时间。

用户态时间=userTime(在用户态执行进程的时间)+niceTime(调整进程优先级的时间)

内核态时间=systemTime(内核态运行的时间)+hardirqTime(处理硬件中断时间)+softIrqTime(处理软件中断时间)

空闲态时间=idleTime(系统空闲期,等待程序运行)

还有waitingTime(指CPU花费在等待IO操作上的总时间),与blocked相似。和stealTime

 

数据来自/proc/stat文件

 bubuko.com,布布扣

%us =(User time + Nice time)/CPU时间*100%

%sy=(System time + Hardirq time +Softirq time)/ CPU时间*100%

%id=(Idle time)/CPU时间*100%

%ni=(Nice time)/CPU时间*100%

%wa=(Waiting time)/CPU时间*100%

%hi=(Hardirq time)/CPU时间*100%

%si=(Softirq time)/CPU时间*100%

%st=(Steal time)/CPU时间*100%

 使用top命令查看

top - 10:28:31 up 2226 days, 19:35, 7 users, load average: 0.52, 0.43, 0.42
Tasks: 470 total, 1 running, 469 sleeping, 0 stopped, 0 zombie
Cpu(s): 1.0%us, 0.6%sy, 0.0%ni, 98.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 32816064k total, 29658804k used, 3157260k free, 1099168k buffers
Swap: 67103496k total, 2045980k used, 65057516k free, 3979548k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
7076 weblogic 20 0 2948m 709m 72m S 23 2.2 3452:23 java
10554 weblogic 20 0 3257m 751m 73m S 19 2.3 3139:00 java
6230 weblogic 20 0 17204 1568 940 R 1 0.0 0:28.58 top
11070 weblogic 20 0 5879m 2.8g 123m S 1 8.8 288:13.68 java
15077 visa 20 0 2668m 655m 3032 S 1 2.0 22519:41 java
20967 root 20 0 5344m 2.6g 23m S 1 8.3 842:53.47 java
19817 root 20 0 5367m 2.5g 30m S 1 8.1 829:30.89 java
23057 root 20 0 5345m 2.7g 24m S 1 8.7 829:28.19 java
58 root 15 -5 0 0 0 S 0 0.0 4:10.17 ksoftirqd/27
5949 root 20 0 8908 424 324 S 0 0.0 6311:42 irqbalance
12010 root 20 0 36844 2376 900 S 0 0.0 167:23.96 redis-server
31222 weblogic 20 0 2660m 563m 67m S 0 1.8 878:31.53 java
1 root 20 0 1064 88 52 S 0 0.0 34:41.57 init
2 root 15 -5 0 0 0 S 0 0.0 0:00.18 kthreadd
3 root RT -5 0 0 0 S 0 0.0 0:00.48 migration/0
4 root 15 -5 0 0 0 S 0 0.0 29:58.07 ksoftirqd/0
5 root RT -5 0 0 0 S 0 0.0 0:02.20 migration/1

备注: top 命令默认情况下,是每 3 秒刷新一次。也可以通过 top  -d <刷新时间间隔> 来指定刷新频率,如top -d 0.1 或top -d 0.01 等。top 执行时,也可以按“s ”键,修改时间间隔。 

weblogic@Bladesystem02:~> cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l          物理CPU数

4    

weblogic@Bladesystem02:~> cat /proc/cpuinfo|grep "cpu cores"|uniq                每个物理CPU中的核数
cpu cores : 8
weblogic@Bladesystem02:~> cat /proc/cpuinfo| grep "processor"| wc -l            所有逻辑CPU的个数
32
weblogic@Bladesystem02:~> cat /proc/cpuinfo |grep name | cut -f2 -d: |uniq -c      CPU信息
32 AMD Opteron(tm) Processor 6136

另外Context Switch Rate也是个非常值得注意的值,因为线程间切换的代价也是非常高的。

引用一个公式:Context Switch Rate = Interrupt Rate + TPS* N

 Load Average是CPU的Load,它所包含的信息不是CPU的使用率状况,而是在一段时间内CPU正在处理以及等待CPU处理的进程数之和,Load Average的值一定要小于系统中所有处理器的总核数,等于就开始有灾难了。cpu的负载主要来自在cpu运行的进程数,队列中准备就绪的进程数和不可中断进程数。

CPU利用率:显示的是程序在运行期间实时占用的CPU百分比,cpu的使用率最好是user空间保持在65%~70%

http://www.cnblogs.com/shengs/p/5148284.html

http://blog.chinaunix.net/uid/12368035/list/7.html

http://tool.oschina.net/uploads/apidocs/jdk-zh/java/util/concurrent/ThreadPoolExecutor.html

http://mp.weixin.qq.com/s?__biz=MzAxODI5ODMwOA==&mid=2666539608&idx=1&sn=89afe8d44bfdab660c28ba18869e65db&scene=0#wechat_redirect

http://blog.csdn.net/wallwind/article/details/51594553

从jvisualvm里面看到的cpu使用率,是机器上面的总的cpu使用率,如果pc机是4核的话,50%的CPU,显示的是12.5%, 100%的CPU,显示的是25%。

新生的小心情
原文地址:https://www.cnblogs.com/jianmianruxin/p/7445521.html