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. API Test WebApiTestClient工具安装及使用

    一.guget安装: 1.解决方案右键-管理解决方案的nuget程序包打开如下图: 搜索WebApiTestClient,然后选择查询出的项目,右边点击安装即可:   2.安装会有如下图提示: 确定即 ...

  2. centos-0 基础

    netstat -nap #会列出所有正在使用的端口及关联的进程/应用kill -9 1777        #杀掉编号为1777的进程(请根据实际情况输入) http://www.cnblogs.c ...

  3. 关于java工程打exe包的一些问题

    这两天在把一个Java project打包成exe文件时碰到了一些问题,现在把这些问题和解决办法记下来. 1.用java swing做前端时,背景图片无法显示 Solution:把jpg图片换成png ...

  4. CF Good Bye 2018

    前言:这次比赛爆炸,比赛时各种想多,导致写到\(D\)题时思路已经乱了,肝了\(1\)个多小时都没肝出来,\(B\)题中途因为没开\(long\ long\)又被\(HACK\)了..\(C\)题因为 ...

  5. 使用PHP实现手机端APP支付宝的支付功能

    最近应业务需求,做了支付宝支付和微信支付,今天分享一下手机端app支付宝支付对接流程,实际开发过程是前后端分离,前端调用后端API接口,实现功能返回数据,我所用的跨挤啊为TP5,大致可以分为四步: 1 ...

  6. 29. pt-table-usage

    pt-table-usage --query="select * from t01 join t02 on t01.id=t02.id where t01.code=2" pt-t ...

  7. day 2:计算机的基础知识,编程语言分类

    本节内容 1,计算机的容量 2,编程语言介绍1,计算机的容量 1位 = 1bit 8bit = 1byte = 1字节 1024bytes = 1k bytes = 1KB 1024个 1024KB ...

  8. Python3 使用pymysql链接MySQL数据库

    1,pymysql安装 pip install pymysql 2,pymysql使用 import pymysql 3,实例查询 import pymysql #获取一个数据库链接 #格式 主机地址 ...

  9. Educational Codeforces Round 58 (Rated for Div. 2) G 线性基

    https://codeforces.com/contest/1101/problem/G 题意 一个有n个数字的数组a[],将区间分成尽可能多段,使得段之间的相互组合异或和不等于零 题解 根据线性基 ...

  10. CodeForces 935E Fafa and Ancient Mathematics (树形DP)

    题意:给定一个表达式,然后让你添加 n 个加号,m 个减号,使得表达式的值最大. 析:首先先要建立一个表达式树,这个应该很好建立,就不说了,dp[u][i][0] 表示 u 这个部分表达式,添加 i ...