锁定老帖子 主题:Java并发--任务执行.
精华帖 (1) :: 良好帖 (8) :: 新手帖 (0) :: 隐藏帖 (10)
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-19
最后修改:2010-06-19
PS: 发到博客的文章竟然发布不到论坛, 所以将文章从博客转来论坛。
package com.ivan.concurrent.charpter6; import java.net.ServerSocket; import java.net.Socket; /** * 顺序化的Web Server. * @author root * OS:Ubuntu 9.04 * Date:2010-6-19 */ public class SingleThreadWebServer { public static void main(String[] args) throws Exception { ServerSocket server=new ServerSocket(8080); while(true){ Socket socket=server.accept(); handleRequest(socket); } } private static void handleRequest(Socket socket) { /** * 做相关的处理……, 比如请求运算与I/O * 这将会导致出现阻塞, 会延迟当前请求的处理, * 而且会产生非常严重的后果,比如: 假死。 * 那样会极度考验用户的耐心,知道他忍无可忍的关闭浏览器。 * 同时,单线程在等待IO操作时,CPU处于闲置状态,这样也降低了资源的利用率 * * 这样的服务器,缺乏良好的吞吐量和快速的响应性。 */ } }
package com.ivan.concurrent.charpter6; import java.net.ServerSocket; import java.net.Socket; public class ThreadPerTaskWebServer { public static void main(String[] args) throws Exception { ServerSocket server=new ServerSocket(80); while(true){ final Socket socket=server.accept(); new Thread(new Runnable(){ public void run() { handleRequest(socket); } }).start(); } } protected static void handleRequest(Socket socket) { /** *相比较而言,这样的处理方式有良好的改进: * 1.执行人物的负载已经脱离主线程,让主循环能更加迅速的重新开始等待下一个连接。提高了响应性 * 2.并发处理任务,多个请求可以同时得到处理,提高了吞吐性 * 3.任务处理代码必须要是线程安全的。防止出现并发性数据共享问题。 * * 这个程序可能在开发阶段运行良好,一旦部署,就可能出现致命的错误, * 我们接着来分析: */ } }
我们看到,上面的代码中,是为每个请求的到来,创建一个新的线程来处理, 那么这样就会有以下的问题出现:
package com.ivan.concurrent.charpter6; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class TaskExecutionWebServer{ private static final int NTHREADS=100; //使用线程池来避免 为每个请求创建一个线程。 private static final Executor threadPool=Executors.newFixedThreadPool(NTHREADS); public static void main(String[] args) throws Exception { ServerSocket server=new ServerSocket(8011); while(true){ final Socket socket=server.accept(); threadPool.execute(new Runnable(){ public void run() { handleRequest(socket); } }); } } protected static void handleRequest(Socket socket) { /** * */ System.out.println(Thread.currentThread().getId()); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } }
线程池:
package com.ivan.concurrent.charpter6; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; /** * 线程池的生命周期是如何管理的? * @author root * OS:Ubuntu 9.04 * Date:2010-6-19 */ public class LifeCycleWebServer { private static final int NTHREADS=100; private static final ExecutorService exec=Executors.newFixedThreadPool(NTHREADS); public void start() throws IOException{ ServerSocket server=new ServerSocket(8011); while(exec.isShutdown()){ try { final Socket socket=server.accept(); exec.execute(new Runnable(){ public void run() { handleRequest(socket); } }); } catch (RejectedExecutionException e) { if(!exec.isShutdown()){ //log.error(...) } } } } protected void handleRequest(Socket socket) { Request req=readRequest(socket); if(isShutDown(req)){ stop(); }else{ dispatchRequest(req); } } public void stop(){ exec.shutdown(); } //~ Mock Object And Function.. private static class Request{ } private Request readRequest(Socket socket) { // TODO Auto-generated method stub return null; } private boolean isShutDown(Request req) { // TODO Auto-generated method stub return false; } private void dispatchRequest(Request req) { // TODO Auto-generated method stub } }
执行策略:
package com.ivan.concurrent.charpter6; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class FutureRenderer { private static final int NTHREADS=100; private static final ExecutorService exec=Executors.newFixedThreadPool(NTHREADS); void renderPage(CharSequence source){ final List<ImageInfo> imageinfos=scanForImageInfo(source); Callable<List<ImageData>> task= new Callable<List<ImageData>>(){ public List<ImageData> call() throws Exception { List<ImageData> result=new ArrayList<ImageData>(); for(ImageInfo imageinfo:imageinfos){ result.add(imageinfo.downloadImage()); } return result; } }; Future<List<ImageData>> future=exec.submit(task); //保证渲染文本与下载图像数据并发执行。 renderText(source); try { /** * 到达需要所有图像的时间点时,主任务会等待future.get调用的结果, * 幸运的话,我们请求的同时,下载已经完成,即使没有,下载也已经预先开始了。 * * 这里还有一定的局限性, 用户可能不希望等待所有图片下载完成后才可以看见, * 他希望下载完成一张图片后,就可以立即看到。 …… 这里还待优化。 */ List<ImageData> imageData=future.get(); for(ImageData data:imageData){ reanderImage(data); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); future.cancel(true);//取消任务 }catch(ExecutionException e){ e.printStackTrace(); } } private void renderText(CharSequence source) { // TODO Auto-generated method stub } private void reanderImage(ImageData data) { // TODO Auto-generated method stub } private List<ImageInfo> scanForImageInfo(CharSequence source) { // TODO Auto-generated method stub return null; } }
package com.ivan.concurrent.charpter6; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class FutureRenderer2 { private static final int NTHREADS=100; private static final ExecutorService exec=Executors.newFixedThreadPool(NTHREADS); void renderPage(CharSequence source){ final List<ImageInfo> imageinfos=scanForImageInfo(source); CompletionService<ImageData> completionService=new ExecutorCompletionService<ImageData>(exec); for(final ImageInfo imageinfo:imageinfos){ completionService.submit(new Callable<ImageData>(){ public ImageData call() throws Exception { //提高性能点一: 将顺序的下载,变成并发的下载,缩短下载时间 return imageinfo.downloadImage(); } }); } renderText(source); try { for(int i=0;i<imageinfos.size();i++){ Future<ImageData> f=completionService.take(); //提高性能点二: 下载完成一张图片后,立刻渲染到页面。 ImageData imagedata=f.get(); reanderImage(imagedata); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); }catch(ExecutionException e){ e.printStackTrace(); } } private void renderText(CharSequence source) { // TODO Auto-generated method stub } private void reanderImage(ImageData data) { // TODO Auto-generated method stub } private List<ImageInfo> scanForImageInfo(CharSequence source) { // TODO Auto-generated method stub return null; } }
附件是整理的doc版本, 总感觉在JE把doc里面的文章复制过来,会有排版问题,所有干脆把doc也一起发上来。 最近离职,正在找下家中, 同时也利用这段空闲时间,准备将自己以前的一些知识做一些整理,做成博文发上来与JE的朋友共享一下,相互交流,在互动的同时,实际上也是在对自己以前的 知识做一遍巩固与复习。 就以这篇文章开头,做为并发系列的开头,后续如果时间充足的话,会继续将相关知识发上。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-06-21
樓主的DOC文檔用的是啥編碼格式?
|
|
返回顶楼 | |
发表时间:2010-06-21
ivaneve 写道 樓主的DOC文檔用的是啥編碼格式?
总结得比较全面,正好熟悉下多线程。 有点像是linux下保存的文件,不过xp解压也没问题,文件名乱码自己改下就好。 |
|
返回顶楼 | |
发表时间:2010-06-21
写的真的很不错。
|
|
返回顶楼 | |
发表时间:2010-06-21
受益良多,写得很全面。
|
|
返回顶楼 | |
发表时间:2010-06-21
Java并发编程实践这本书我找了好久了。实体书到处缺货。
谁有电子版分享一下? |
|
返回顶楼 | |
发表时间:2010-06-21
lz的描述加代码 正好解决我们现在项目中遇到的问题 很不错
|
|
返回顶楼 | |
发表时间:2010-06-21
楼主这篇帖子写的很不错。。。
|
|
返回顶楼 | |
发表时间:2010-06-21
lz写得不错,支持一下。面试前准备一下多线程编程还是很有用的,命中率很高。
|
|
返回顶楼 | |
发表时间:2010-06-22
嗯,写的是不错 这里有个帖子,给大家分享一下,文中写了很多线程的基础 http://bbs.misonsoft.com/thread-1088-1-1.html |
|
返回顶楼 | |