JavaScript的单线程性质以及同步ajax提交

本文转自:http://www.phpweblog.net/rainman/archive/2009/01/05/6267.html

How JavaScript Timers Work

从基础的层面来讲,理解JavaScript的定时器是如何工作的是非常重要的。计时器的执行常常和我们的直观想象不同,那是因为JavaScript引擎是单线程的。我们先来认识一下下面三个函数是如何控制计时器的。

  • var id = setTimeout(fn, delay); – 初始化一个计时器,然后在指定的时间间隔后执行。该函数返回一个唯一的标志ID(Number类型),我们可以使用它来取消计时器。
  • var id = setInterval(fn, delay); – 和setTimeout有些类似,但它是连续调用一个函数(时间间隔是delay参数)直到它被取消。
  • clearInterval(id);, clearTimeout(id); – 使用计时器ID(setTimeout 和 setInterval的返回值)来取消计时器回调的发生

为了理解计时器的内在执行原理,有一个重要的概念需要加以探讨:计时器的延迟(delay)是无法得到保障的。由于所有JavaScript代码是在一个线程里执行的,所有异步事件(例如,鼠标点击和计时器)只有拥有执行机会时才会执行。用一个很好的图表加以说明:

在这个图表中有许多信息需要理解,如果完全理解了它们,你会对JavaScript引擎如何实现异步事件有一个很好的认识。

继续阅读“JavaScript的单线程性质以及同步ajax提交”

基于Spring打造简单高效通用的异步任务处理系统(转)

本文之前,今天发现使用spring-batch也能够达到相同的效果,不过相比spring-batch,本文使用的数据表更少,且相应的逻辑更简洁,特转如下。
本文转自:http://blog.csdn.net/sfdev/article/details/4056114 原文作者:sfdev

背景

随着应用系统功能的不断新增,而某些功能的实现对实时性要求并不是那么高,但是逻辑却很复杂、执行比较耗时,比如涉及外部系统调用、多数据源等等;此时,我们就希望可以让这些复杂的业务逻辑放在后台执行,而前台与用户的交互可以不用等待,从而提高用户体验;

另外,从系统架构这个层面来说,我们也希望按照不同功能来拆分,以保持各个系统之间的低耦合,当一个系统出现问题时不会影响到其他系统,并且对于独立的各个系统,我们可以专门进行性能优化、监控等;所以我们需要通用、高效的异步任务处理系统;

设计目标

打造轻量级、简单、高效、通用、高扩展性、高可靠性的异步任务处理系统!

系统设计

要实现类似的异步处理系统,相信大家首先想到的就是JMS,Alibaba里面也有基于JMS的异步处理系统,而且该系统在网店系统中应用非常广泛;但由于目前我们阿里软件采用了不同的技术框架,所以不能直接拿来使用;况且,该系统为了实现异步任务系统的并发,采取了JMS与MDB结合的策略,所以系统就依赖于EJB了,这样系统就变得笨重了,由此系统部署的应用服务器必须要支持EJB,一些轻量级的不支持EJB规范的应用服务器就没法部署了;

考虑到如上的系统设计目标,我们的设计思路为:任务DB持久化 + Spring封装Job调度、线程池

继续阅读“基于Spring打造简单高效通用的异步任务处理系统(转)”

从swing分发线程机制上理解多线程

    本文参考了 http://space.itpub.net/13685345/viewspace-374940,原文作者:javagui
    在多线程编程当中,总会提到图形编程,比如java中的swing,并一再提出,在swing中,一切都是单线程的。所有的界面更新操作都必须在排队似地进行。这样的目的在于,避免由于多线程的处理导致界面渲染以及组件排列异常,同时也避免了由于多线程带来的加锁访问以及等待锁的情况发生。

    EventQueue的派发机制由单独的一个线程管理,这个线程称为事件派发线程(EDT)”。和其他很多桌面API一样,Swing将GUI请求放入一个事件队列中执行。
    这个可以这样来理解,界面上所有的操作,包括点击按钮,编辑文字等。这些操作都会产生一系列的事件,而这些事件均按钮一定的顺序(通常是事件发生的顺序)依次的插入到事件队列中。而分线线程则按照顺序从事件队列中依次一个一个地取出事件对象,并调用事件的相应方法来运行处理事件的方法。
    在整个处理阶段,分发线程必须要等到一个事件处理方法运行结束之后,才会处理下一个事件。在这个过程中,肯定有些事件处理得快,比如普通的点击按钮改变颜色的这种操作;而有些事件则会非常的慢,比如点击按钮运行一个长时间的数据压缩。我们希望,处理得慢的事件在处理时不致于影响其它事件的处理。

继续阅读“从swing分发线程机制上理解多线程”

java线程中断的本质,简单的设计思想(转)

    本文部分内容转自:http://blog.csdn.net/dlite/article/details/4218105,原文作者为:DLite。仅部分摘录。

    一直以来,用过很多线程的应用,最经常使用的就是开启一个线程,然后就不管之,任其运行。或者运行成功,或者运行失败,都跟主线程无关。稍微用得多一点的就是使用对象的wait,再配合线程之间的调度,当线程需要中断时,直接中断其,然后被中断的线程抛出一个中断异常,自然地被中止运行了(因为没有捕获异常,被中断线程方法自然停止运行)。

    但是长久地来看,并没有了解线程中断的实质。从简单上来讲,中断一个线程,可以理解为中断这个线程的运行,就像使用thread.stop方法所运行的一样;并且实际运行效果也是这样,因为线程抛出了异常,而我们没捕获,则线程自然被中断,听起来中断一个线程就和停止线程运行一个效果。但实际上,这是两个完全不一样的工作方式。
    所谓的线程停止,是指这个线程已经不再运行了;而中断,则是指线程由于某种原因被外力(或自身)要求停止不再运行,但线程仍然拥有是否继续运行(或停止运行)的权利,关键在于线程如何处理这个中断的动作。简单一点理解就是,线程中断,只是向线程发送了一个标记,表示这个线程应该中断了,但如何停止运行是由线程自身或处理中断的行为所决定的。
        以下为引用内容:

    JVM内部确实为每个线程维护了一个中断标记。
    通常情况下,调用线程的interrupt方法,并不能立即引发中断,只是设置了JVM内部的中断标记。因此,通过检查中断标记,应用程序可以做一些特殊操作,也可以完全忽略中断。
    你可能想,如果JVM只提供了这种简陋的中断机制,那和应用程序自己定义中断变量并轮询的方法相比,基本也没有什么优势。
    JVM内部中断变量的主要优势,就是对于某些情况,提供了模拟自动“中断陷入”的机制。
    在执行涉及线程调度的阻塞调用时(例如wait、sleep和join),如果发生中断,被阻塞线程会“尽可能快的”抛出InterruptedException。
    所谓“尽可能快”,我猜测JVM就是在线程调度调度的间隙检查中断变量,速度取决于JVM的实现和硬件的性能。

    另外,有jdk源代码为证,下方法为thread的interrupt方法:

    public void interrupt() {
	if (this != Thread.currentThread())
	    checkAccess();

	synchronized (blockerLock) {
	    Interruptible b = blocker;
	    if (b != null) {
//以下此方法,包括调用2,均只设置一个中断标记,下一行的英文注解为原jdk注解
		interrupt0();		// Just to set the interrupt flag
		b.interrupt();
		return;
	    }
	}
	interrupt0();//调用2
    }

    所以,线程中断就是为指定的线程设定一个中断变量,然后当被操作的线程接收到这个变量之后,就努力地抛出一个中断异常出来。由于在一般情况下,我们没有catch这个异常,所以,线程被自然地异常退出了,而且不会影响到主线程。
    在正式地线程调试中,肯定需要对线程的中断行为,定制不同的处理方式,比如安全地释放资源,然后安全的退出等。

继续阅读“java线程中断的本质,简单的设计思想(转)”

在java web项目中慎用Executors以及非守护线程

     最近研究embeded tomcat,特别是关于tomcat启动和关闭的模块。通过查看相应的源代码, 我们知道tomcat的关闭是通过往相应的关闭端口发送指定的关闭指令来达到关闭tomcat的目的。但是有的时候,通过shutdown.bat或shutdown.sh却不能有效地关闭tomcat,网上也有很多人提出这个问题。通过相关资料,最后问题出现线程上。

继续阅读“在java web项目中慎用Executors以及非守护线程”