xylz,imxylz

关注后端架构、中间件、分布式和并发编程

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  111 随笔 :: 10 文章 :: 2680 评论 :: 0 Trackbacks

J2EE

Java Core Knowledge/Java Web Solution
posted @ 2013-10-16 00:33 imxylz 阅读(9091) | 评论 (8)  编辑

posted @ 2013-08-17 17:44 imxylz 阅读(3806) | 评论 (3)  编辑

posted @ 2012-12-26 12:02 imxylz 阅读(17466) | 评论 (31)  编辑

posted @ 2012-03-15 18:30 imxylz 阅读(11446) | 评论 (16)  编辑

posted @ 2012-02-08 16:41 imxylz 阅读(3985) | 评论 (1)  编辑

     摘要: 刚看到这个月的编程语言排行榜,很显然java的霸主地位很快就会在发达国家被挤掉,C语言依然是王者(想想上个月自己买的两个C语言的书,冷汗直流)。看来我迟早要回归C,这才是真正的王道。



非常令人吃惊的是C++语言依然不够坚挺,由于Windows 7/Windows 8的发力,C#很快就会抢占C++的市场,估计很快就会将C++从前三名中挤下去。



iPhone/iPad的热销让Object C继续火热,前十的位置还是可以持续很久的,这一点毋庸置疑。移动设备开发的高端人才现在是高薪难求,如果有时间我也要继续关注下。  阅读全文
posted @ 2011-12-06 11:25 imxylz 阅读(4582) | 评论 (8)  编辑

     摘要: Zookeeper客户端和服务端维持一个长连接,每隔10s向服务端发送一个心跳,服务端返回客户端一个响应。这就是一个Session连接,拥有全局唯一的session id。Session连接通常是一直有效,如果因为网络原因断开了连接,客户端会使用相同的session id进行重连。由于服务端保留了session的各种状态,尤其是各种瞬时节点是否删除依赖于session是否失效。
Session失效问题

通常客户端主动关闭连接认为是一次session失效。另外也有可能因为其它未知原因,例如网络超时导致的session失效问题。在服务端看来,无法区分session失效是何种情况,一次一旦发生session失效,一定时间后就会将session持有的所有watcher以及瞬时节点删除。
而对于Zookeeper客户端而言,一旦发生失效不知道是否该重连,这涉及到watcher和瞬时节点问题,因此Zookeeper客户端认为,一旦发生了seesion失效,那么就认为客户端死掉了。从而所有操作都不能够进行。参考 How should I handle SESSION  阅读全文
posted @ 2011-12-05 13:57 imxylz 阅读(28451) | 评论 (8)  编辑

posted @ 2011-06-17 09:25 imxylz 阅读(5131) | 评论 (3)  编辑

posted @ 2011-06-12 00:24 imxylz 阅读(11188) | 评论 (36)  编辑

     摘要: 当Ajax遇到GBK/GB2312,我们恨不能将所有项目的编码统一改为UTF-8。显然这个做法,成本太高了。下面给出了一个完善的解决方案。此方案不仅仅限于Ajax提交数据,也适用于普通访问请求。  阅读全文
posted @ 2011-06-10 23:46 imxylz 阅读(8649) | 评论 (6)  编辑

     摘要: 这一节中我们将详细讨论线程池是如何执行一个任务的,尤其是如何处理线程池的大小、核心大小、最大大小、任务队列等之间的关系的。  阅读全文
posted @ 2011-02-11 23:48 imxylz 阅读(11607) | 评论 (2)  编辑

     摘要: 本着开发的原则,既然用到了别人家的东西,所以决定公开出来,也算是给别人一个参考。  阅读全文
posted @ 2011-01-05 10:00 imxylz 阅读(4532) | 评论 (1)  编辑

     摘要: Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。
下面这张图完整描述了线程池的类体系结构。  阅读全文
posted @ 2010-12-21 23:32 imxylz 阅读(13699) | 评论 (4)  编辑

     摘要: 最近的项目使用的是旧的ibatis2.x版本,有时候为了方便调试,想输出SQL执行的语句和参数。我记得应该有某些logger的日志级别修改为DEBUG就可以看到。当然为了方便可以直接在log4j(如果使用log4j的话)的root日志级别修改为DEBUG,并且输出appender的接受级别修改为DEBUG就可以了。这样是可以看到日志信息(SQL/参数)等,但是同时也输出了过多的其它logger信息,显然在一个稍微大一点的系统里面debug的信息应该都是非常多的,不说别的,光是spring的日志就够好多页了。
为了解决过多的日志,翻出ibatis源码,看了下。ibatis的执行流程大致是这样的。  阅读全文
posted @ 2010-12-05 15:17 imxylz 阅读(3486) | 评论 (3)  编辑

posted @ 2010-12-03 16:13 imxylz 阅读(9989) | 评论 (7)  编辑

posted @ 2010-11-02 16:09 imxylz 阅读(5719) | 评论 (19)  编辑

posted @ 2010-08-12 00:54 imxylz 阅读(3082) | 评论 (14)  编辑

posted @ 2010-07-16 11:59 imxylz 阅读(8994) | 评论 (4)  编辑

     摘要:
这一节主要是谈谈读写锁的实现。
上一节中提到,ReadWriteLock看起来有两个锁:readLock/writeLock。如果真的是两个锁的话,它们之间又是如何相互影响的呢?
事实上在ReentrantReadWriteLock里锁的实现是靠java.util.concurrent.locks.ReentrantReadWriteLock.Sync完成的。这个类看起来比较眼熟,实际上它是AQS的一个子类,这中类似的结构在CountDownLatch、ReentrantLock、Semaphore里面都存在。同样它也有两种实现:公平锁和非公平锁,也就是java.util.concurrent.locks.ReentrantReadWriteLock.FairSync和java.util.concurrent.locks.ReentrantReadWriteLock.NonfairSync。这里暂且不提。
在ReentrantReadWriteLock里面的锁主体就是一个Sync,也就是上面提到的FairSync或者NonfairSync,所以说实际  阅读全文
posted @ 2010-07-15 00:41 imxylz 阅读(20242) | 评论 (1)  编辑

     摘要: 从这一节开始介绍锁里面的最后一个工具:读写锁(ReadWriteLock)。
ReentrantLock 实现了标准的互斥操作,也就是一次只能有一个线程持有锁,也即所谓独占锁的概念。前面的章节中一直在强调这个特点。显然这个特点在一定程度上面减低了吞吐量,实际上独占锁是一种保守的锁策略,在这种情况下任何“读/读”,“写/读”,“写/写”操作都不能同时发生。但是同样需要强调的一个概念是,锁是有一定的开销的,当并发比较大的时候,锁的开销就比较客观了。所以如果可能的话就尽量少用锁,非要用锁的话就尝试看能否改造为读写锁。
ReadWriteLock描述的是:一个资源能够被多个读线程访问,或者被一个写线程访问,但是不能同时存在读写线程。也就是说读写锁使用的场合是一个共享资源被大量读取操作,而只有少量的写操作(修改数据)。清单1描述了ReadWriteLock的API。  阅读全文
posted @ 2010-07-14 14:18 imxylz 阅读(24180) | 评论 (4)  编辑

     摘要: Semaphore 是一个计数信号量。从概念上讲,信号量维护了一个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
说白了,Semaphore是一个计数器,在计数器不为0的时候对线程就放行,一旦达到0,那么所有请求资源的新线程都会被阻塞,包括增加请求到许可的线程,也就是说Semaphore不是可重入的。每一次请求一个许可都会导致计数器减少1,同样每次释放一个许可都会导致计数器增加1,一旦达到了0,新的许可请求线程将被挂起。
缓存池整好使用此思想来实现的,比如链接池、对象池等。  阅读全文
posted @ 2010-07-13 22:41 imxylz 阅读(23303) | 评论 (2)  编辑

     摘要:
如果说CountDownLatch是一次性的,那么CyclicBarrier正好可以循环使用。它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。所谓屏障点就是一组任务执行完毕的时刻。
  阅读全文
posted @ 2010-07-12 23:33 imxylz 阅读(22313) | 评论 (2)  编辑

     摘要: 此小节介绍几个与锁有关的有用工具。
闭锁(Latch)
闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态。通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态。也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成。
CountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生。CountDownLatch有一个正数计数器,countDown方法对计数器做减操作,await方法等待计数器达到0。所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时。  阅读全文
posted @ 2010-07-09 09:21 imxylz 阅读(29251) | 评论 (6)  编辑

     摘要: 本小节介绍锁释放Lock.unlock()。
Release/TryRelease
unlock操作实际上就调用了AQS的release操作,释放持有的锁。  阅读全文
posted @ 2010-07-08 12:33 imxylz 阅读(30398) | 评论 (11)  编辑

     摘要: 接上篇,这篇从Lock.lock/unlock开始。特别说明在没有特殊情况下所有程序、API、文档都是基于JDK 6.0的。
在没有深入了解内部机制及实现之前,先了解下为什么会存在公平锁和非公平锁。公平锁保证一个阻塞的线程最终能够获得锁,因为是有序的,所以总是可以按照请求的顺序获得锁。不公平锁意味着后请求锁的线程可能在其前面排列的休眠线程恢复前拿到锁,这样就有可能提高并发的性能。这是因为通常情况下挂起的线程重新开始与它真正开始运行,二者之间会产生严重的延时。因此非公平锁就可以利用这段时间完成操作。这是非公平锁在某些时候比公平锁性能要好的原因之一。  阅读全文
posted @ 2010-07-07 00:05 imxylz 阅读(40052) | 评论 (6)  编辑

     摘要: 在理解J.U.C原理以及锁机制之前,我们来介绍J.U.C框架最核心也是最复杂的一个基础类:java.util.concurrent.locks.AbstractQueuedSynchronizer。

AQS
AbstractQueuedSynchronizer,简称AQS,是J.U.C最复杂的一个类,导致绝大多数讲解并发原理或者实战的时候都不会提到此类。但是虚心的作者愿意借助自己有限的能力和精力来探讨一二(参考资源中也有一些作者做了部分的分析。)。
首先从理论知识开始,在了解了相关原理后会针对源码进行一些分析,最后加上一些实战来描述。  阅读全文
posted @ 2010-07-06 18:29 imxylz 阅读(52906) | 评论 (3)  编辑

     摘要: 前面的章节主要谈谈原子操作,至于与原子操作一些相关的问题或者说陷阱就放到最后的总结篇来整体说明。从这一章开始花少量的篇幅谈谈锁机制。
上一个章节中谈到了锁机制,并且针对于原子操作谈了一些相关的概念和设计思想。接下来的文章中,尽可能的深入研究锁机制,并且理解里面的原理和实际应用场合。
尽管synchronized在语法上已经足够简单了,在JDK 5之前只能借助此实现,但是由于是独占锁,性能却不高,因此JDK 5以后就开始借助于JNI来完成更高级的锁实现。
JDK 5中的锁是接口java.util.concurrent.locks.Lock。另外java.util.concurrent.locks.ReadWriteLock提供了一对可供读写并发的锁。根据前面的规则,我们从java.util.concurrent.locks.Lock的API开始。  阅读全文
posted @ 2010-07-05 13:37 imxylz 阅读(42083) | 评论 (11)  编辑

     摘要: 在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁(后面的章节还会谈到锁)。
锁机制存在以下问题:
(1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。
(2)一个线程持有锁会导致其它所有需要此锁的线程挂起。
(3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。
volatile是不错的机制,但是volatile不能保证原子性。因此对于同步最终还是要回到锁机制上来。
独占锁是一种悲观锁,synchronized就是一种独占锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一个更加有效的锁就是乐观锁。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。  阅读全文
posted @ 2010-07-04 18:03 imxylz 阅读(47892) | 评论 (19)  编辑

     摘要: 在这个小结里面重点讨论原子操作的原理和设计思想。
由于在下一个章节中会谈到锁机制,因此此小节中会适当引入锁的概念。
在Java Concurrency in Practice中是这样定义线程安全的:
当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替运行,并且不需要额外的同步及在调用方代码不必做其他的协调,这个类的行为仍然是正确的,那么这个类就是线程安全的。  阅读全文
posted @ 2010-07-03 20:40 imxylz 阅读(46423) | 评论 (16)  编辑

     摘要: 在这一部分开始讨论数组原子操作和一些其他的原子操作。
AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray的API类似,选择有代表性的AtomicIntegerArray来描述这些问题。
int get(int i)
获取位置 i 的当前值。很显然,由于这个是数组操作,就有索引越界的问题(IndexOutOfBoundsException异常)。

对于下面的API起始和AtomicInteger是类似的,这种通过方法、参数的名称就能够得到函数意义的写法是非常值得称赞的。在《重构:改善既有代码的设计》和《代码整洁之道》中都非常推崇这种做法。  阅读全文
posted @ 2010-07-02 14:19 imxylz 阅读(48027) | 评论 (6)  编辑

     摘要: 从相对简单的Atomic入手(java.util.concurrent是基于Queue的并发包,而Queue,很多情况下使用到了Atomic操作,因此首先从这里开始)。很多情况下我们只是需要一个简单的、高效的、线程安全的递增递减方案。注意,这里有三个条件:简单,意味着程序员尽可能少的操作底层或者实现起来要比较容易;高效意味着耗用资源要少,程序处理速度要快;线程安全也非常重要,这个在多线程下能保证数据的正确性。这三个条件看起来比较简单,但是实现起来却难以令人满意。
通常情况下,在Java里面,++i或者--i不是线程安全的,这里面有三个独立的操作:或者变量当前值,为该值+1/-1,然后写回新的值。在没有额外资源可以利用的情况下,只能使用加锁才能保证读-改-写这三个操作时“原子性”的。  阅读全文
posted @ 2010-07-01 15:21 imxylz 阅读(65652) | 评论 (2)  编辑

     摘要: 去年年底有一个Guice的研究计划,可惜由于工作“繁忙”加上实际工作中没有用上导致“无疾而终”,最终只是完成了Guice的初步学习教程,深入的研究没有继续进行下去。
最近一直用的比较多的就是java.util.concurrent(J.U.C),实际上这块一直也没有完全深入研究,这次准备花点时间研究下Java里面整个并发体系。初步的设想包括比较大的方便(包括硬件、软件、思想以及误区等等),因此可能会持续较长的时间。这块内容也是Java在多线程方面引以为豪的一部分,深入这一部分不仅对整个Java体系有更深的了解,也对工作、学习的态度有多帮助。  阅读全文
posted @ 2010-06-30 18:09 imxylz 阅读(69025) | 评论 (8)  编辑

posted @ 2010-01-31 00:00 imxylz 阅读(19863) | 评论 (0)  编辑

     摘要: 以前有段时间需要知道某些类在什么jar包中,这样当出现ClassNotFoundException或者NoClassDefFoundError的时候我们就可以去找这个类在什么jar包中然后去引用此jar包即可。在我们的系统很小的时候我恨不能都将jar包放入eclipse中,这样借助 eclipse平台查找类就非常方便了。包括非常有用的Ctrl+Shift+T,Ctrl+T,Reference search等等,但是当工程多了大了的时候,上百个jar包放入eclipse中那个速度完全不是我能忍受的,稍微动一下就看到CPU一直在那抖动。好吧,用maven,更慢,简直受不了,所以大多数时候Maven是一个比较好的批处理工具,和UI结合起来还不是很好用。

我发现我非常需要这个从jar包中寻找类的功能,我只需要看看我的类在什么地方而已,仅次而已!于是自己就写了一个类查找器。非常简单就是遍历所有的jar包中的类,当匹配类名称的时候就显示类所在的jar包。
有以下几个特性:

* 允许添加jar包,zip包
* 允许匹  阅读全文
posted @ 2009-12-31 17:07 imxylz 阅读(20846) | 评论 (11)  编辑

     摘要: 本章节继续讨论Google Guice与第三方的整合,这里主要讨论如何整合JMX的服务,通过guice-jmx插件我们可以很方便的将我们的服务注入到JMX服务中,这样就能够通过远程调用来控制我们的服务。  阅读全文
posted @ 2009-12-31 15:35 imxylz 阅读(19812) | 评论 (3)  编辑

     摘要: Google Guice 整合第三方组件。

在《Google Guice 入门教程06 – Web 和Servlet》 中我们看到了Guice 整合Struts 2的应用。本章节继续讨论Guice整合其它第三方组件的应用。

本章节重点谈Guice与DWR和Spring的整合。
  阅读全文
posted @ 2009-12-29 00:11 imxylz 阅读(27310) | 评论 (5)  编辑

     摘要: 本章节主要讲Guice中如何开发Servlet,当然了作为IOC的容器,Guice在这方面仍然局限于依赖注入功能。作为WEB方面的开发就不能不提Struts,这里着重谈如何与Struts 2进行整合。  阅读全文
posted @ 2009-12-27 22:58 imxylz 阅读(16750) | 评论 (1)  编辑

     摘要: 本章节主要讨论Guice中AOP的使用,其中花了一些篇幅谈AOP的概念,然后通过一些API和例子来说明AOP的具体使用过程。  阅读全文
posted @ 2009-12-27 00:16 imxylz 阅读(17724) | 评论 (2)  编辑

     摘要: 本章节继续讨论依赖注入的其他话题,包括作用域(scope,这里有一个与线程绑定的作用域例子)、立即初始化(Eagerly Loading Bindings)、运行阶段(Stage)、选项注入(Optional Injection)等等。   阅读全文
posted @ 2009-12-25 18:02 imxylz 阅读(16581) | 评论 (1)  编辑

     摘要: 在我们64位的CenterOS上,指定了JVM的最大堆内存为5500M,但是在top和进程status中可以看到实际占用内存已经远远大于5500M,那么JVM到底占用多大内存?如果做到控制JVM的占用内存大小?  阅读全文
posted @ 2009-12-23 19:51 imxylz 阅读(3526) | 评论 (1)  编辑

Full J2EE Archive


©2009-2014 IMXYLZ