任务执行和任务处理的异步执行

最近在看《深入剖析Tomcat》,在第四章有讲解Tomcat的默认连接器,和这个连接器有着密切关系的是一个处理器。一个连接器可以对应多个处理器。连接器的作用是从客户端的请求中提取出Socket,然后把Socket传递给处理器来处理用户的请求。需要注意的是连接器的关注点是在接收请求,分派给他下游的处理器去执行,在把Socket传递下去后,连接器在这次请求中的任务已经完成。这里可以看到,连接器和处理器他们是异步进行的,异步的处理为多线程的执行提供了可能。

在这里我要说的是,在看了Tomcat的源码实现后,有了点自己的想法,写出了两个相对类似的类,以自己以后参考以及分享给大家。

 1 public class AsyncCaller implements Runnable{
 2
 3     private static Logger logger = Logger.getLogger(AsyncCaller.class);
 4
 5     private Stack<AsyncExecutor> executors = new Stack<AsyncExecutor>();
 6     private boolean shutdown = false;
 7
 8     private static int MAX_THREAD_NUMBER = 10;
 9
10     public static void main(String[] args) {
11         AsyncCaller ac = new AsyncCaller();
12         ac.init();
13         new Thread(ac).start();
14     }
15
16     public void init() {
17         for( int i = 0; i < MAX_THREAD_NUMBER; i++ ) {
18             AsyncExecutor ae = new AsyncExecutor(i, this);
19             ae.threadStart();
20             executors.add(ae);
21         }
22     }
23
24     public void recycle(AsyncExecutor ae) {
25         this.executors.push(ae);
26     }
27
28     @Override
29     public void run() {
30         while( !shutdown ) {
31             logger.info("Input:");
32             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
33             String input = null;
34             try {
35                  input = br.readLine();
36             } catch (IOException e) {
37                 e.printStackTrace();
38             }
39
40             if( "shutdown".equals(input) ) {
41                 shutdown = true;
42             } else {
43                 int baseNumber = 0;
44                 try {
45                     baseNumber = Integer.parseInt(input);
46                 } catch (Exception e) {
47                     e.printStackTrace();
48                 }
49
50                 if( !executors.isEmpty() ) {
51                     AsyncExecutor ae = executors.pop();
52                     ae.assignBaseNumber(baseNumber);
53                 } else {
54                     logger.info("no more executor, waiting for next time");
55                 }
56
57             }
58
59         }
60     }
61
62 }
  1 public class AsyncExecutor implements Runnable{
  2
  3     private static Logger logger = Logger.getLogger(AsyncExecutor.class);
  4
  5     private long result = 0l;
  6     private boolean available = false;
  7
  8     private long baseNumber;
  9     private int threadIndex;
 10
 11     private boolean shutdown = false;
 12     private AsyncCaller asyncCaller;
 13
 14     public AsyncExecutor(int threadIndex, AsyncCaller ac) {
 15         this.threadIndex = threadIndex;
 16         this.asyncCaller = ac;
 17     }
 18
 19     public void threadStart() {
 20         Thread t = new Thread(this, String.valueOf(threadIndex));
 21         t.start();
 22     }
 23
 24     /*
 25      * 所有本类的实例在新建时,就通过调用Thread.start()方法
 26      * 来开始执行操作,在进入方法awaitBaseNumber()时,每个
 27      * 线程都在等待一个状态位(available)的变化,状态位的变化
 28      * 表明处理器线程等待的数据已经准备好,接下来,这个线程可以
 29      * 来处理真正的业务逻辑,待处理完毕后,把当前的线程放回线程池,
 30      * 以便重复利用
 31      */
 32     @Override
 33     public void run() {
 34         while( !shutdown ) {
 35             // 等待期望的数据,此时线程在此处一直处于停滞的状态(Blocking),
 36             // 直到处理器线程(AsyncCaller)准备好数据,然后通过改变状态位,available
 37             // 让本线程重新恢复运行的状态
 38             long baseNumber = awaitBaseNumber();
 39             // 处理真正的逻辑
 40             process(baseNumber);
 41             //把当前线程放回线程池,以便重复利用
 42             this.asyncCaller.recycle(this);
 43         }
 44
 45     }
 46
 47     /*
 48      * 正是assignBaseNumber()方法和awaitBaseNumber()方法相互影响,
 49      * 相互制约,才使得多线程异步执行成为可能
 50      */
 51     public synchronized void assignBaseNumber( long baseNumber ) {
 52
 53         while( available ) {
 54             try {
 55                 wait();
 56             } catch (InterruptedException e) {
 57                 e.printStackTrace();
 58             }
 59         }
 60
 61         this.baseNumber = baseNumber;
 62         available = true;
 63         notifyAll();
 64
 65     }
 66
 67     public synchronized long awaitBaseNumber() {
 68
 69         while( !available ) {
 70             try {
 71                 wait();
 72             } catch (InterruptedException e) {
 73                 e.printStackTrace();
 74             }
 75         }
 76
 77         long baseNumber = this.baseNumber;
 78
 79         available = false;
 80         notifyAll();
 81         return  baseNumber;
 82     }
 83
 84     private void process(long baseNumber) {
 85         logger.info("Thread:" + Thread.currentThread().getName() + " base number:" + baseNumber);
 86         timeCostingCalculation(baseNumber);
 87     }
 88
 89     private void timeCostingCalculation(long baseNumber) {
 90
 91         result = baseNumber;
 92         for( int i = 0; i < 10_000; i++ ) {
 93             result = result + 1;
 94             try {
 95                 Thread.sleep(1);
 96             } catch (InterruptedException e) {
 97                 e.printStackTrace();
 98             }
 99         }
100         logger.info("Thread:" + Thread.currentThread().getName() + " result:" + result);
101     }
102
103
104 }

参考书籍

1,深入剖析Tomcat

时间: 2024-12-17 07:35:47

任务执行和任务处理的异步执行的相关文章

什么是异步执行?异步执行和多线程执行的不同?

什么是异步执行? 异步执行:就是不需要等待别的任务完,就立刻执行同步执行刚好相反,异步执行,所以可以多个进程执行 异步跟多线程有什么区别? 异步同步是交互方式?多线程是性能任务的说法

Delphi中ADO异步执行方式

当ADO开始处理数据后,应用程序必须等到ADO处理完毕之后才可以继续执行.但是除了同步执行方式之外,ADO也提供了异步执行的方式,允许当ADO处理时,应用程序仍然能够先继续执行.而当ADO处理数据完毕之后,ADO会以事件的方式通知应用程序,此时应用程序可以再根据ADO执行的结果来采取相应的动作.使用异步执行方式有许多用途,例如,如果应用程序需要处理花费大量时间的动作,那么ADO可以选择以异步执行方式让ADO在后台执行,而让应用程序继续处理图形用户接口或用户输入的数据.在ADO中使用异步执行方式非

关于异步执行

异步执行模式 异步执行模式,是指语句在异步执行模式下,各语句执行结束的顺序与语句执行开始的顺序并不一定相同. 例如 查询操作,客户机上的应用程序在向服务器发出了查 询操作的指令后,将立刻执行查询语句指令的下一条 语句,而不需要等到服务器将查询结果返回客户机端.异步执行方式使应用程序能摆 脱单个任务的牵制,提高了灵活性和应用程序的执行 效率.但异步执行模式也存在一些问题,如它增加了编程的复杂性,特别是编写互用性(interoperable)要求较高 的程序. 在负荷很重的客户/服务器系 统中,适宜

异步执行js脚本——防止阻塞

JS允许我们修改页面中的所有方面:内容,样式和用户进行交互时的行为. 但是js同样可以阻塞DOM树的形成并且延迟页面的渲染. 让你的js变成异步执行,并且减少不必要的js文件从而提高性能. JavaScript可以查询和修改DOM和CSSOM JavaScript的执行阻塞了CSSOM的执行 JavaScript 阻塞了DOM的形成,除非特殊声明js异步执行 js是一个同步语言可以修改网页的任何方面: <html> <head> <meta name="viewpo

Windows 商店应用程序异步执行task和调整task优先级

在制作WP8.1手电筒的时候遇到一个问题,手电筒有时候能够点亮有时候点不亮. 在MSDN论坛上面有人告诉我可能是优先级的问题示意叫我使用CoreDispatcher 将task任务提高权限,但是发现还是不行. 后来发现点亮闪关灯需要在UI线程中触发,不能再异步中实现,感觉和画图有点类似不能在非主线程中绘制图片. 下面我就分享怎么利用CoreDispatcher改变task任务的优先级(不过还没有验证,因为我还没有遇到需要改变优先级的task,但是依据Windows运行时API的说明应该是正确的改

node js 异步执行流程控制模块Async介绍

1.Async介绍 sync是一个流程控制工具包,提供了直接而强大的异步功能.基于Javascript为Node.js设计,同时也可以直接在浏览器中使用. Async提供了大约20个函数,包括常用的 map, reduce, filter, forEach 等,异步流程控制模式包括,串行(series),并行(parallel),瀑布(waterfall)等. 项目地址:https://github.com/caolan/async 2. Async安装 npm install async 3.

多线程异步执行脚本

获取远程计算机信息: $d=get-date $servers="10.4.34.41","10.4.34.40","10.4.34.36","10.4.34.37","10.4.34.39" $serverpass="Dell1950" $UserName="Administrator" #定义线程数量$throttleLimit = 5$SessionState

异步执行的运行机制

异步执行的运行机制如下.(同步执行也是如此,因为它可以被视为没有异步任务的异步执行.) (1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack). (2)主线程之外,还存在一个"任务队列"(task queue).只要异步任务有了运行结果,就在"任务队列"之中放置一个事件. (3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件.那些对应的异步任务

使用spring的@Async异步执行方法

应用场景: 1.某些耗时较长的而用户不需要等待该方法的处理结果 2.某些耗时较长的方法,后面的程序不需要用到这个方法的处理结果时 在spring的配置文件中加入对异步执行的支持 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.spri