转载标明出处:http://blog.csdn.net/lmj623565791/article/details/26938985

继续并发,貌似并发的文章很少有人看啊~哈~

今天准备详细介绍java并发包下的Executor,以及Java提供了很多灵活的且极其方便的线程池的创建。

嗯,那就慢慢说,大家肯定都学过Socket,JavaSe的时候写聊天程序,游戏的服务器,以及Android程序自己需要提供服务器的,都会拿Socket来自己写个:

最初我们的服务器可能写成这样:

1、单线程服务器
package com.zhy.concurrency.executors;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket; /**
* 单线程Web服务器
*
* @author zhy
*
*/
public class SingleThreadWebServer
{ public static void main(String[] args) throws IOException
{ ServerSocket server = new ServerSocket(7711);
while (true)
{
Socket client = server.accept();
handleReq(client);
} } /**
* 处理请求
* @param client
*/
private static void handleReq(Socket client)
{
} }

这样的服务器代码很简单,理论上也是正确的,但是在实现的环境中却很糟糕,因为它每次只能处理一个请求,如果每个请求的耗时过长,后面的请求会长时间等待或者超时错误。

于是乎,出现了下面这种写法:

2、每个请求分配一个线程的服务器
package com.zhy.concurrency.executors;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 为每个请求分配一个线程
* @author zhy
*
*/
public class TaskPreThreadServer
{
public static void main(String[] args) throws IOException
{
ServerSocket server = new ServerSocket(8811);
while (true)
{
final Socket client = server.accept();
new Thread()
{
public void run()
{
handleReq(client);
};
}.start();
}
} protected static void handleReq(Socket client)
{ }
}

为每一个请求开辟一个线程,首先我得承认我也经常用这样的写法~但是我们还是要吐槽下这样写法的不足:

a、线程的生命周期的开销还是相当高的,大量的线程的创建将消耗大量的计算机资源

b、可创建线程的数量存在一个限制值(这个值由平台觉得,且受很多因素的制约),如果超过这个限制,可能会报OOM错误

c、在一定范围内,增加线程可以提高系统吞吐量,但是超过了这个范围,就物极必反了,只会降低程序的执行速度。

所以我们要继续改进我们的服务器代码,Executor提供了非常方便的方式:

3、基于Executor的服务器
package com.zhy.concurrency.executors;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors; /**
* 基于Executor的服务器
* @author zhy
*
*/
public class TaskExecutionServer
{
private static final int THREAD_COUNT = 100;
private static final Executor exec = Executors
.newFixedThreadPool(THREAD_COUNT); public static void main(String[] args) throws IOException
{
ServerSocket server = new ServerSocket(9911);
while (true)
{
final Socket client = server.accept();
Runnable task = new Runnable()
{
@Override
public void run()
{
handleReq(client);
}
};
exec.execute(task);
} } protected static void handleReq(Socket client)
{ }
}

创建一个固定长度的线程池,既解决了单线程的阻塞问题,也解决了无限创建线程带来的内存消耗过多等问题。

4、Executors的API介绍

Java类库提供了许多静态方法来创建一个线程池:

a、newFixedThreadPool 创建一个固定长度的线程池,当到达线程最大数量时,线程池的规模将不再变化。

b、newCachedThreadPool 创建一个可缓存的线程池,如果当前线程池的规模超出了处理需求,将回收空的线程;当需求增加时,会增加线程数量;线程池规模无限制。

c、newSingleThreadPoolExecutor 创建一个单线程的Executor,确保任务对了,串行执行

d、newScheduledThreadPool 创建一个固定长度的线程池,而且以延迟或者定时的方式来执行,类似Timer;后面后单独使用Blog介绍它与Timer区别

小结一下:在线程池中执行任务比为每个任务分配一个线程优势更多,通过重用现有的线程而不是创建新线程,可以在处理多个请求时分摊线程创建和销毁产生的巨大的开销。当请求到达时,通常工作线程已经存在,提高了响应性;通过配置线程池的大小,可以创建足够多的线程使CPU达到忙碌状态,还可以防止线程太多耗尽计算机的资源。

好了,结束~欢迎大家留言~

Java 并发专题 : Executor详细介绍 打造基于Executor的Web服务器的更多相关文章

  1. Java 并发专题 : Executor具体介绍 打造基于Executor的Webserver

    转载标明出处:http://blog.csdn.net/lmj623565791/article/details/26938985 继续并发,貌似并发的文章非常少有人看啊~哈~ 今天准备具体介绍jav ...

  2. Java并发性和多线程介绍

    java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题,多开线程就好: 快速响应,异步式 ...

  3. Java 并发和多线程(一) Java并发性和多线程介绍[转]

    作者:Jakob Jenkov 译者:Simon-SZ  校对:方腾飞 http://tutorials.jenkov.com/java-concurrency/index.html 在过去单CPU时 ...

  4. 基于HttpListener的web服务器

    写在前面 前面两篇文章分别介绍了基于原始socket的web服务器和基于tcpListener的web服务器,本篇文章将继续介绍另外一种基于HttpListener的. HttpListener Ht ...

  5. 基于TcpListener的web服务器

    写在前面 上篇文章根据<asp.net 本质论>书上提供的例子,实现了一个简单的web服务器,本篇文章将介绍另一种实现方式——基于TcpListener的web服务器. TcpListen ...

  6. Java 并发专题 : CyclicBarrier 打造一个安全的门禁系统

    继续并发专题~ 这次介绍CyclicBarrier:看一眼API的注释: /** * A synchronization aid that allows a set of threads to all ...

  7. Java并发专题

    ——参考于码农求职小助手公众号 1.并行和并发有什么区别? 1. 并行是指两个或者多个事件在同一时刻发生:而并发是指两个或多个事件在同一时间间隔发生: 2. 并行是在不同实体上的多个事件,并发是在同一 ...

  8. Java 并发专题 :FutureTask 实现预加载数据 在线看电子书、浏览器浏览网页等

    继续并发专题~ FutureTask 有点类似Runnable,都可以通过Thread来启动,不过FutureTask可以返回执行完毕的数据,并且FutureTask的get方法支持阻塞. 由于:Fu ...

  9. Java并发专题(二)线程安全

    前言 随着时代的发展,CPU核数的增加和计算速度的提升,串行化的任务执行显然是对资源的极大浪费,掌握多线程是每个程序员必须掌握的技巧.但是同时多线程也是一把双刃剑,带来了共享资源安全的隐患.在本节会介 ...

随机推荐

  1. 辛星跟您玩转vim第一节之vim的下载与三种模式

    首先值得一提的是,我的vim教程pdf版本号已经写完了,大家能够去下载,这里是csdn的下载地址:点此下载 ,假设左边的下载地址挂掉了,也能够自行在浏览器以下输入例如以下地址进行下载:http://d ...

  2. POJ2528 Mayor&#39;s posters 【线段树】+【成段更新】+【离散化】

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 39795   Accepted: 11552 ...

  3. codeforces 577

    codeforces 577A 题目链接:http://codeforces.com/problemset/problem/577/A 题目大意:给出一个n*n的表格,每个表格对应的值为横坐标*纵坐标 ...

  4. firebug使用

    查看网页的header是优化web应用的关键一环,从header中,可以检查到非常 多的信息:网页在squid中的缓存时间(age).客户端缓存时间(expires).是否有最后修改时间(last-m ...

  5. poj3621 Sightseeing Cows --- 01分数规划

    典型的求最优比例环问题 參考资料: http://blog.csdn.net/hhaile/article/details/8883652 此题中,给出每一个点和每条边的权值,求一个环使 ans=∑点 ...

  6. BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第3章节--SharePoint 2013 开发者工具 站点设置

    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第3章节--SharePoint 2013 开发者工具 站点设置         你应该熟悉(假设还咩有)的SharePo ...

  7. JMS的样例

    1.JMS是一个由AS提供的Message服务.它能接受消息产生者(Message Provider)所发出的消息,并把消息转发给消息消费者(Message  Consumer).2.JMS提供2种类 ...

  8. leetcode day6 -- String to Integer (atoi) &amp;&amp; Best Time to Buy and Sell Stock I II III

    1.  String to Integer (atoi) Implement atoi to convert a string to an integer. Hint: Carefully con ...

  9. POJ1505&amp;&amp;UVa714 Copying Books(DP)

    Copying Books Time Limit: 3000MS Memory Limit: 10000K Total Submissions: 7109 Accepted: 2221 Descrip ...

  10. fopen()惹的祸

    读一个文件,刚开始只读“r”  打开,读数据,刚开始的一段数据还好,但只读了一小部分就读不到正确的数据了,后来反复的看自己的代码,比对文件的内容,纠结了一天了都,感觉什么都没写错啊.心里总认为是这个文 ...