1、线程池简介:

多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。

假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。

如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。

一个线程池包括以下四个基本组成部分:

  1、线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;

  2、工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;

  3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;

  4、任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
                
线程池技术正是关注如何缩短或调整T1,T3时间的技术,从而提高服务器程序性能的。它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了。线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,看一个例子:

假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成。在线程池中,线程数一般是固定的,所以产生线程总数不会超过线程池中线程的数目,而如果服务器不利用线程池来处理这些请求则线程总数为50000。一般线程池大小是远小于50000。所以利用线程池的服务器程序不会为了创建50000而在处理请求时浪费时间,从而提高效率。

线程池实现代码:

 package com.wb.thread;

 import java.util.LinkedList;
import java.util.List; /**
* 线程池类
* @author wangbo
*
*/
public class ThreadPool { private static int worker_num = 5;//线程池中线程的个数,默认为5 private WorkThread[] workthreads;//工作线程 private static volatile int finished_task = 0;//未处理的任务 private List<Runnable> taskQueue = new LinkedList<Runnable>();//任务队列 private static ThreadPool threadPool; /**
* 无参构造器,创建线程池
*/
private ThreadPool(){
this(5);
} /**
* 含参构造器,创建线程池
* @param num
*/
private ThreadPool(int num){
worker_num = num;
workthreads = new WorkThread[num];
for (int i = 0; i < workthreads.length; i++) {
workthreads[i] = new WorkThread();
workthreads[i].start();//开启线程
}
} /**
* 获得一个默认线程个数的线程池
* @return
*/
public static ThreadPool getThreadPool(){
return getThreadPool(ThreadPool.worker_num);
} /**
* 获得一个指定线程个数的线程池
* @param num
* @return
*/
public static ThreadPool getThreadPool(int num) {
if (num <= 0) {
num = ThreadPool.worker_num;
}
if (threadPool == null) {
threadPool = new ThreadPool(num);
}
return threadPool;
} /**
* 将任务单个添加到队列
* @param task
*/
public void execute(Runnable task){
synchronized (taskQueue) {
taskQueue.add(task);
taskQueue.notify();
}
} /**
* 将任务批量添加到队列
* @param tasks
*/
public void execute(Runnable[] tasks){
synchronized (taskQueue) {
for (Runnable runnable : tasks) {
taskQueue.add(runnable);
}
taskQueue.notify();
}
} /**
* 将任务批量添加到队列
* @param tasks
*/
public void execute(List<Runnable> tasks){
synchronized (taskQueue) {
for (Runnable runnable : tasks) {
taskQueue.add(runnable);
}
taskQueue.notify();
}
} /**
* 销毁线程池
*/
public void destroy(){
//还有任务没有执行完
while(!taskQueue.isEmpty()){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//停止工作线程,且置为null
for (int i = 0; i < workthreads.length; i++) {
workthreads[i].stopWorker();
workthreads[i] = null;
}
threadPool = null;
taskQueue.clear();//清空队列
} /**
* 获取工作线程的个数
* @return
*/
public int getWorkThreadNumber(){
return worker_num;
} /**
* 获取已完成任务数量
* @return
*/
public int getFinishedTaskNumber(){
return finished_task;
} /**
* 获取未完成任务数量
* @return
*/
public int getWaitTaskNumber(){
return taskQueue.size();
} /**
* 获取线程池信息
*/
@Override
public String toString() {
return "工作线程数量:" + getWorkThreadNumber()
+ ",已完成任务数量" + getFinishedTaskNumber()
+ ",未完成任务数量" + getWaitTaskNumber(); } /**
* 内部类,工作线程
* @author wangbo
*
*/
private class WorkThread extends Thread{ private boolean isRunning = true;//线程有效标志 @Override
public void run() {
Runnable runnable = null;
while (isRunning) {
synchronized (taskQueue) {
//队列为空
while (isRunning && taskQueue.isEmpty()) {
try {
taskQueue.wait(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//队列不为空
if (!taskQueue.isEmpty()) {
runnable = taskQueue.remove(0);//去除任务
}
}
if (runnable != null) {
runnable.run();//执行任务
}
finished_task++;
runnable = null;
} } /**
* 停止线程
*/
public void stopWorker() {
isRunning = false;
} } }

测试代码:

 package com.wb.thread;

 public class ThreadPoolTest {

      public static void main(String[] args) {
// 创建3个线程的线程池
ThreadPool t = ThreadPool.getThreadPool(3);
t.execute(new Runnable[] { new Task(), new Task(), new Task() });
t.execute(new Runnable[] { new Task(), new Task(), new Task() });
System.out.println(t);
t.destroy();//所有线程都执行完成才destory
System.out.println(t);
} // 任务类
static class Task implements Runnable { private static volatile int i = 1; @Override
public void run() {// 执行任务
System.out.println("任务 " + (i++) + " 完成");
}
} }

2、java类库中提供的线程池简介:

java.util.concurrent包提供了现成的线程池的实现。

示例代码:

 package com.wb.thread;

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* newCachedThreadPool()
* 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
* 有任务才会创建线程,空闲线程会被保留60s
* @author wangbo
*
*/
public class ThreadPoolExecutorTest1 { public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index);
System.out.println(Thread.currentThread().getName());
}
});
}
} }
 package com.wb.thread;

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* newFixedThreadPool(int nThreads)
* 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
* 线程池中包含固定数目的线程,空闲线程会一直保留,参数nThreads表示设定线程池中线程的数目
* @author wangbo
*
*/
public class ThreadPoolExecutorTest2 { public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(index);
System.out.println(Thread.currentThread().getName());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
} }
 package com.wb.thread;

 import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* newScheduledThreadPool(int corePoolSize)
* 线程池能按时间计划来执行任务,允许用户设定计划执行任务的时间。
* 参数corePoolSize设定线程池中线程最小数目,当任务较多时,线程池可能会创建更多的工作线程来执行任务。
* @author wangbo
*
*/
public class ThreadPoolExecutorTest3 { public static void main(String[] args) { method1();
method2(); } /**
* 延迟3s执行
*/
private static void method1(){
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
scheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("延迟2s执行");
}
}, 2, TimeUnit.SECONDS);
} /**
* 延迟2s执行后每3s执行一次
*/
private static void method2() {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("延迟2s执行后每3s执行一次");
System.out.println(Thread.currentThread().getName());
}
}, 2, 3, TimeUnit.SECONDS);
} }
 package com.wb.thread;

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* newSingleThreadExecutor(int nThreads)
* 线程池中只有一个线程,它依次执行每个任务。
* 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
* @author wangbo
*
*/
public class ThreadPoolExecutorTest4 { public static void main(String[] args) {
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(index);
System.out.println(Thread.currentThread().getName());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
} }
 package com.wb.thread;

 import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* newSingleThreadScheduledExecutor()
* 线程池中只有一个线程,它能按照时间计划执行每个任务。
* @author wangbo
*
*/
public class ThreadPoolExecutorTest5 { public static void main(String[] args) { method1();
method2(); } /**
* 延迟3s执行
*/
private static void method1(){
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
scheduledThreadPool.schedule(new Runnable() {
public void run() {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("延迟2s执行");
}
}, 2, TimeUnit.SECONDS);
} /**
* 延迟2s执行后每3s执行一次
*/
private static void method2() {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
public void run() {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
System.out.println("延迟2s执行后每3s执行一次");
System.out.println(Thread.currentThread().getName());
}
}, 2, 3, TimeUnit.SECONDS);
} }

Java 线程池的原理及实现的更多相关文章

  1. Java线程池的原理及几类线程池的介绍

    刚刚研究了一下线程池,如果有不足之处,请大家不吝赐教,大家共同学习.共同交流. 在什么情况下使用线程池? 单个任务处理的时间比较短 将需处理的任务的数量大 使用线程池的好处: 减少在创建和销毁线程上所 ...

  2. 并发编程(十二)—— Java 线程池 实现原理与源码深度解析 之 submit 方法 (二)

    在上一篇<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法.这篇文章是接着上一篇文章 ...

  3. Java 线程池的原理与实现 (转)

        最近在学习线程池.内存控制等关于提高程序运行性能方面的编程技术,在网上看到有一哥们写得不错,故和大家一起分享. [分享]Java 线程池的原理与实现 这几天主要是狂看源程序,在弥补了一些以前知 ...

  4. Java线程池实现原理及其在美团业务中的实践

    本文转载自Java线程池实现原理及其在美团业务中的实践 导语 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供 ...

  5. 我眼中的java线程池实现原理

    最近在看java线程池实现方面的源码,在此做个小结,因为网上关于线程池源码分析的博客挺多的,我也不打算重复造轮子啦,仅仅用纯语言描述的方式做做总结啦! 个人认为要想理解清楚java线程池实现原理,明白 ...

  6. Java 线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

  7. Java 线程池(ThreadPoolExecutor)原理解析

    在我们的开发中“池”的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 有关java线程技术文章还可以推荐阅读:<关于java多线程w ...

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

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

  9. 深入浅出JAVA线程池使用原理1

    前言: Java中的线程池是并发框架中运用最多的,几乎所有需要异步或并发执行任务的程序都可以使用线程池,线程池主要有三个好处: 1.降低资源消耗:可以重复使用已经创建的线程降低线程创建和销毁带来的消耗 ...

  10. Java线程池(ThreadPoolExecutor)原理分析与使用

    在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使用线程池的好处 1.降低资源消耗 可以重复利用 ...

随机推荐

  1. 11.Redis缓存设计

    11.Redis缓存设计11.1 缓存的收益和成本11.2 缓存更新策略11.3 缓存粒度控制11.4 穿透优化11.5 无底洞优化11.6 雪崩优化11.7 热点key重建优化11.8 本章重点回顾

  2. scrapy 爬取智联招聘

    准备工作 1. scrapy startproject Jobs 2. cd Jobs 3. scrapy genspider ZhaopinSpider www.zhaopin.com 4. scr ...

  3. 分析easyswoole3.0源码,consoleTcpService(六)

    前文讲过可以通过配置开启一个tcp服务,叫做consoleTcpservice.EasySwoole\EasySwoole\Core::83行 (new TcpService(Config::getI ...

  4. Kudu基本操作及概念

    Kudu:    针对 Apache Hadoop 平台而开发的列式存储管理器. 使用场景:    适用于那些既有随机访问,也有批量数据扫描的复合场景.    高计算量的场景.    使用了高性能的存 ...

  5. optional install error: Package require os(darwin) not compatible with your platform(win32)

    解决方法: cnpm rebuild node-sass cnpm install

  6. Sliverlight调用WebService跨域问题解决

    在SilverlightApplication正常添加webservice(承载网站中建webservice,这样就不存在跨域问题了,即域名一样如:localhost:4676) http://loc ...

  7. linux学习第十九天 (Linux就该这么学) 结课了

    今天最后一天课程了,结课了,还有点舍不得那,在些也祝 李老师 事业蒸蒸日上,超来超好, 今天内容是部署了 LNMP 部署动态网站环境(linux  +nginx+mysql+php) 安装文件挺别多, ...

  8. 从 Basic Paxos 到 Multi Paxos 到 Raft

    在朴素Paxos算法中, 各个节点经过 Prepare 和 Accept 阶段, 会达成一个值, 这个值一旦达成, 就不能被修改, 如下例子: 图示1 上面的操作几乎没有任何实用价值, 于是演变成下面 ...

  9. 数据库database

    1.创建数据库:create datebase financials create database if not exists financilas 2.查看数据库(所有):     show da ...

  10. select标签操作

    //遍历select标签 WebElement select = driver.findElement(By.tagName("select")); List<WebElem ...