为每一个请求开辟一个线程,首先我得承认我也经常用这样的写法~但是我们还是要吐槽下这样写法的不足: a、线程的生命周期的开销还是相当高的,大量的线程的创建将消耗大量的计算机资源 b、可创建线程的数量存在一个限制值(这个值由平台觉得,且受很多因素的制约),如果超过这个限制,可能会报OOM错误 c、在一定范围内,增加线程可以提高系统吞吐量,但是超过了这个范围,就物极必反了,只会降低程序的执行速度。 所以我们要继续改进我们的服务器代码,Executor提供了非常方便的方式。
Executors的API介绍 Java类库提供了许多静态方法来创建一个线程池: a、newFixedThreadPool 创建一个固定长度的线程池,当到达线程最大数量时,线程池的规模将不再变化。 b、newCachedThreadPool 创建一个可缓存的线程池,如果当前线程池的规模超出了处理需求,将回收空的线程;当需求增加时,会增加线程数量;线程池规模无限制。 c、newSingleThreadPoolExecutor 创建一个单线程的Executor,确保任务对了,串行执行 d、newScheduledThreadPool 创建一个固定长度的线程池,而且以延迟或者定时的方式来执行,类似Timer;后面后单独使用Blog介绍它与Timer区别 小结一下:在线程池中执行任务比为每个任务分配一个线程优势更多,通过重用现有的线程而不是创建新线程,可以在处理多个请求时分摊线程创建和销毁产生的巨大的开销。当请求到达时,通常工作线程已经存在,提高了响应性;通过配置线程池的大小,可以创建足够多的线程使CPU达到忙碌状态,还可以防止线程太多耗尽计算机的资源。
public class TaskExecutionServer{ private static final int COUNT=10; private static final Executor ex= Executors.newFixedThreadPool(COUNT); public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(7754); while(true){ Socket sc = ss.accept(); Runnable task=new Runnable(){ @Override public void run(){ action(sc); } }; ex.execute(task); } } public static void action(Socket sc){ } }