少年阿宾

那些青春的岁月

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

#

1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,
如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断
如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情

ReentrantLock获取锁定与三种方式:
a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁
b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
c)tryLock(long timeout,TimeUnit unit), 如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;
posted @ 2013-05-23 12:39 abin 阅读(675) | 评论 (0)编辑 收藏

MySQL 当记录不存在时插入,当记录存在时更新.........具体解决办法如下:
1、INSERT INTO… ON DUPLICATE KEY UPDATE
如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则执行旧行UPDATE。
使用环境:
例如,如果列a被定义为UNIQUE,并且包含值1,则以下两个语句具有相同的效果:
首先建表(先说UNIQUE):
create table abin1(
id int not null unique,
username varchar(100),
password varchar(100)
)
insert into abin1 (id,username,password) values (1,'abin1','varyall1') on duplicate key update username='abin12',password='varyall12';

其次再说主键(primary key)类型的:
create table abin2(
id int not null,
username varchar(100),
password varchar(100),
constraint pk_abin2 primary key(id)
)
执行语句:
insert into abin2 (id,username,password) values (1,'abin1','varyall1') on duplicate key update username='abin12',password='varyall12';




2、插入单行记录:如果不存在插入记录,如果存在记录的话,就不再插入
insert into abin2 (id,username,password) select 1,'abin12','varyall12' from dual
where not exists (select k.* from abin2 k where k.id=1)


3、示例一:插入多条记录

假设有一个主键为 id 的 abin2表,可以使用下面的语句:

insert into abin2 (id,username,password) select 1,'abin12','varyall12' from dual
where not exists (select k.* from abin2 k where k.id=1)

4、
我们在使用数据库时可能会经常遇到这种情况。如果一个表在一个字段上建立了唯一索引,当我们再向这个表中使用已经存在的键值插入一条记录,那将会抛出一个主键冲突的
错误。当然,我们可能想用新记录的值来覆盖原来的记录值。如果使用传统的做法,必须先使用DELETE语句删除原先的记录,然后再使用INSERT插入新的记录。而在MySQL中为
我们提供了一种新的解决方案,这就是REPLACE语句。使用REPLACE插入一条记录时,如果不重复,REPLACE就和INSERT的功能一样,如果有重复记录,REPLACE就使用新记录的值
来替换原来的记录值。

具体用法:
replace into abin2 (id,username,password) values (2,'abin','varyall')




http://blog.csdn.net/kesaihao862/article/details/6718443

posted @ 2013-05-14 11:14 abin 阅读(526) | 评论 (0)编辑 收藏

    1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的.

        2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的

        3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.

        4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的,是之前提过的BlockingQueue的又一实现。它给我们提供了在线程之间交换单一元素的极轻量级方法.

    其中LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue. 

 http://www.2cto.com/kf/201212/175028.html

posted @ 2013-05-13 16:54 abin 阅读(646) | 评论 (1)编辑 收藏

1.根据ROWID来分
select * from t_xiaoxi where rowid in(select rid from (select rownum rn,rid from(select rowid rid,cid from

t_xiaoxi  order by cid desc) where rownum<10000) where rn>9980) order by cid desc;
执行时间0.03秒
2.按分析函数来分
select * from (select t.*,row_number() over(order by cid desc) rk from t_xiaoxi t) where rk<10000 and rk>9980;
执行时间1.01秒
3.按ROWNUM来分
select * from(select t.*,rownum rn from(select * from t_xiaoxi order by cid desc) t where rownum<10000) where

rn>9980;执行时间0.1秒
其中t_xiaoxi为表名称,cid为表的关键字段,取按CID降序排序后的第9981-9999条记录,t_xiaoxi表有70000多条记录
个人感觉1的效率最好,3次之,2最差

posted @ 2013-05-10 13:29 abin 阅读(465) | 评论 (0)编辑 收藏

锁:

  1. 内置锁 (监视器锁): 每个java对象都可以做一个实现同步的锁,这些锁被成为内置锁. 获得锁的唯一途径就是进入有这个锁保护的代码块或方法
  2. 重入锁: 由于内置锁是可重入的,因此如果某个线程试图获得一个以已经由他自己持有的锁, 那么这个请求就会成功.重入意味着获取锁的操作粒度是"线程",而不是"调用"

volatile 使用条件(必须同时满足所有条件):

  1. 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值
  2. 该变量不会与其他状态变量一起纳入不变性条件中
  3. 在访问变量时间不需要加锁


 


 

高并发术语



术语

英文单词

描述

比较并交换

Compare and Swap

CAS操作需要输入两个数值,一个旧值(期望操作前的值)和一个新值,在操作期间先比较下旧值有没有发生变化,如果没有发生变化,才交换成新值,发生了变化则不交换

CPU流水线

CPU pipeline

CPU流水线的工作方式就象工业生产上的装配流水线,在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线,然后将一条X86指令分成5~6步后再由这些电路单元分别执行,这样就能实现在一个CPU时钟周期完成一条指令,因此提高CPU的运算速度

内存顺序冲突

Memory order violation

内存顺序冲突一般是由假共享引起,假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效,当出现这个内存顺序冲突时,CPU必须清空流水线

共享变量


在多个线程之间能够被共享的变量被称为共享变量。共享变量包括所有的实例变量,静态变量和数组元素。他们都被存放在堆内存中,Volatile只作用于共享变量。

内存屏障

Memory Barriers

是一组处理器指令,用于实现对内存操作的顺序限制。

缓冲行

Cache line

缓存中可以分配的最小存储单位。处理器填写缓存线时会加载整个缓存线,需要使用多个主内存读周期。

原子操作

Atomic operations

不可中断的一个或一系列操作。

缓存行填充

cache line fill

当处理器识别到从内存中读取操作数是可缓存的,处理器读取整个缓存行到适当的缓存(L1,L2,L3的或所有)

缓存命中

cache hit

如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时,处理器从缓存中读取操作数,而不是从内存。

写命中

write hit

当处理器将操作数写回到一个内存缓存的区域时,它首先会检查这个缓存的内存地址是否在缓存行中,如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存,而不是写回到内存,这个操作被称为写命中。



 

synchronized

volatile

concurrent 

在并发编程中很常用的实用工具类。此包包括了几个小的、已标准化的可扩展框架,以及一些提供有用功能的类,没有这些类,这些功能会很难实现或实现起来冗长乏味。下面简要描述主要的组件。另请参阅 locks 和 atomic 包。

执行程序

接口。Executor 是一个简单的标准化接口,用于定义类似于线程的自定义子系统,包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同,可能在新创建的线程中,现有的任务执行线程中,或者调用 execute() 的线程中执行任务,并且可能顺序或并发执行。ExecutorService 提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排,并允许受控制的关闭。ScheduledExecutorService 子接口及相关的接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法,可执行由 Callable 表示的任何函数,结果类似于 RunnableFuture 返回函数的结果,允许确定执行是否完成,并提供取消执行的方法。RunnableFuture 是拥有 run 方法的 Future,run 方法执行时将设置其结果。

实现。类 ThreadPoolExecutor 和 ScheduledThreadPoolExecutor 提供可调的、灵活的线程池。Executors 类提供大多数 Executor 的常见类型和配置的工厂方法,以及使用它们的几种实用工具方法。其他基于 Executor 的实用工具包括具体类 FutureTask,它提供 Future 的常见可扩展实现,以及 ExecutorCompletionService,它有助于协调对异步任务组的处理。

队列

java.util.concurrent ConcurrentLinkedQueue 类提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent 中的五个实现都支持扩展的 BlockingQueue 接口,该接口定义了 put 和 take 的阻塞版本:LinkedBlockingQueueArrayBlockingQueueSynchronousQueuePriorityBlockingQueue 和 DelayQueue。这些不同的类覆盖了生产者-使用者、消息传递、并行任务执行和相关并发设计的大多数常见使用的上下文。BlockingDeque 接口扩展 BlockingQueue,以支持 FIFO 和 LIFO(基于堆栈)操作。LinkedBlockingDeque 类提供一个实现。

计时

TimeUnit 类为指定和控制基于超时的操作提供了多重粒度(包括纳秒级)。该包中的大多数类除了包含不确定的等待之外,还包含基于超时的操作。在使用超时的所有情况中,超时指定了在表明已超时前该方法应该等待的最少时间。在超时发生后,实现会“尽力”检测超时。但是,在检测超时与超时之后再次实际执行线程之间可能要经过不确定的时间。接受超时期参数的所有方法将小于等于 0 的值视为根本不会等待。要“永远”等待,可以使用 Long.MAX_VALUE 值。

同步器

四个类可协助实现常见的专用同步语句。Semaphore 是一个经典的并发工具。CountDownLatch 是一个极其简单但又极其常用的实用工具,用于在保持给定数目的信号、事件或条件前阻塞执行。CyclicBarrier 是一个可重置的多路同步点,在某些并行编程风格中很有用。Exchanger 允许两个线程在 collection 点交换对象,它在多流水线设计中是有用的。

并发 Collection

除队列外,此包还提供了设计用于多线程上下文中的 Collection 实现:ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetCopyOnWriteArrayList 和 CopyOnWriteArraySet。当期望许多线程访问一个给定 collection 时,ConcurrentHashMap 通常优于同步的 HashMapConcurrentSkipListMap 通常优于同步的 TreeMap。当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList 优于同步的 ArrayList

此包中与某些类一起使用的“Concurrent&rdquo前缀;是一种简写,表明与类似的“同步”类有所不同。例如,java.util.Hashtable 和Collections.synchronizedMap(new HashMap()) 是同步的,但 ConcurrentHashMap 则是“并发的”。并发 collection 是线程安全的,但是不受单个排他锁的管理。在 ConcurrentHashMap 这一特定情况下,它可以安全地允许进行任意数目的并发读取,以及数目可调的并发写入。需要通过单个锁不允许对 collection 的所有访问时,“同步”类是很有用的,其代价是较差的可伸缩性。在期望多个线程访问公共 collection 的其他情况中,通常“并发”版本要更好一些。当 collection 是未共享的,或者仅保持其他锁时 collection 是可访问的情况下,非同步 collection 则要更好一些。

大多数并发 Collection 实现(包括大多数 Queue)与常规的 java.util 约定也不同,因为它们的迭代器提供了弱一致的,而不是快速失败的遍历。弱一致的迭代器是线程安全的,但是在迭代时没有必要冻结 collection,所以它不一定反映自迭代器创建以来的所有更新。

内存一致性属性

Java Language Specification 第 17 章定义了内存操作(如共享变量的读写)的 happen-before 关系。只有写入操作 happen-before 读取操作时,才保证一个线程写入的结果对另一个线程的读取是可视的。synchronized 和 volatile 构造 happen-before 关系,Thread.start() 和Thread.join() 方法形成 happen-before 关系。尤其是:
  • 线程中的每个操作 happen-before 稍后按程序顺序传入的该线程中的每个操作。
  • 一个解除锁监视器的(synchronized 阻塞或方法退出)happen-before 相同监视器的每个后续锁(synchronized 阻塞或方法进入)。并且因为 happen-before 关系是可传递的,所以解除锁定之前的线程的所有操作 happen-before 锁定该监视器的任何线程后续的所有操作。
  • 写入 volatile 字段 happen-before 每个后续读取相同字段。volatile 字段的读取和写入与进入和退出监视器具有相似的内存一致性效果,但 需要互斥锁。
  • 在线程上调用 start happen-before 已启动的线程中的任何线程。
  • 线程中的所有操作 happen-before 从该线程上的 join 成功返回的任何其他线程。
java.util.concurrent 中所有类的方法及其子包扩展了这些对更高级别同步的保证。尤其是:
  • 线程中将一个对象放入任何并发 collection 之前的操作 happen-before 从另一线程中的 collection 访问或移除该元素的后续操作。
  • 线程中向 Executor 提交 Runnable 之前的操作 happen-before 其执行开始。同样适用于向 ExecutorService 提交 Callables
  • 异步计算(由 Future 表示)所采取的操作 happen-before 通过另一线程中 Future.get() 获取结果后续的操作。
  • “释放”同步储存方法(如 Lock.unlockSemaphore.release 和 CountDownLatch.countDown)之前的操作 happen-before 另一线程中相同同步储存对象成功“获取”方法(如 Lock.lockSemaphore.acquireCondition.await 和 CountDownLatch.await)的后续操作。
  • 对于通过 Exchanger 成功交换对象的每个线程对,每个线程中 exchange() 之前的操作 happen-before 另一线程中对应 exchange() 后续的操作。
  • 调用 CyclicBarrier.await 之前的操作 happen-before 屏障操作所执行的操作,屏障操作所执行的操作 happen-before 从另一线程中对应await 成功返回的后续操作。

 

Condition

Condition 将 Object 监视器方法(waitnotify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 做的那样。

Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

作为一个示例,假定有一个绑定的缓冲区,它支持 put 和 take 方法。如果试图在空的缓冲区上执行 take 操作,则在某一个项变得可用之前,线程将一直阻塞;如果试图在满的缓冲区上执行 put 操作,则在有空间变得可用之前,线程将一直阻塞。我们喜欢在单独的等待 set 中保存 put 线程和 take 线程,这样就可以在缓冲区中的项或空间变得可用时利用最佳规划,一次只通知一个线程。可以使用两个 Condition 实例来做到这一点。

 class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length) 
         notFull.await();
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }

   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0) 
         notEmpty.await();
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   } 
 }
 

ArrayBlockingQueue 类提供了这项功能,因此没有理由去实现这个示例类。)

Condition 实现可以提供不同于 Object 监视器方法的行为和语义,比如受保证的通知排序,或者在执行通知时不需要保持一个锁。如果某个实现提供了这样特殊的语义,则该实现必须记录这些语义。

注意,Condition 实例只是一些普通的对象,它们自身可以用作 synchronized 语句中的目标,并且可以调用自己的 wait 和notification 监视器方法。获取 Condition 实例的监视器锁或者使用其监视器方法,与获取和该 Condition 相关的 Lock 或使用其 waiting 和 signalling 方法没有什么特定的关系。为了避免混淆,建议除了在其自身的实现中之外,切勿以这种方式使用Condition 实例。

除非另行说明,否则为任何参数传递 null 值将导致抛出 NullPointerException

实现注意事项

在等待 Condition 时,允许发生“虚假唤醒”,这通常作为对基础平台语义的让步。对于大多数应用程序,这带来的实际影响很小,因为 Condition 应该总是在一个循环中被等待,并测试正被等待的状态声明。某个实现可以随意移除可能的虚假唤醒,但建议应用程序程序员总是假定这些虚假唤醒可能发生,因此总是在一个循环中等待。

三种形式的条件等待(可中断、不可中断和超时)在一些平台上的实现以及它们的性能特征可能会有所不同。尤其是它可能很难提供这些特性和维护特定语义,比如排序保证。更进一步地说,中断线程实际挂起的能力在所有平台上并不是总是可行的。

因此,并不要求某个实现为所有三种形式的等待定义完全相同的保证或语义,也不要求其支持中断线程的实际挂起。

要求实现清楚地记录每个等待方法提供的语义和保证,在某个实现不支持中断线程的挂起时,它必须遵从此接口中定义的中断语义。

由于中断通常意味着取消,而又通常很少进行中断检查,因此实现可以先于普通方法的返回来对中断进行响应。即使出现在另一个操作后的中断可能会释放线程锁时也是如此。实现应记录此行为。




posted @ 2013-05-06 18:33 abin 阅读(618) | 评论 (1)编辑 收藏

第一部分:JMOCK测试接口

package com.abin.lee.mock.jmock;

/**
 * Created with IntelliJ IDEA.
 * User: abin
 * Date: 13-5-6
 * Time: 下午12:23
 * To change this template use File | Settings | File Templates.
 */
public interface UserService {
    public String getMessage(String message);
}





package com.abin.lee.mock.jmock;

/**
 * Created with IntelliJ IDEA.
 * User: abin
 * Date: 13-5-6
 * Time: 下午12:24
 * To change this template use File | Settings | File Templates.
 */
public class UserServiceImpl implements UserService {
    @Override
    public String getMessage(String message) {
        String result="";
        result="hello "+message;
        return result;
    }
}





package com.abin.lee.mock.jmock;

import junit.framework.TestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Created with IntelliJ IDEA.
 * User: abin
 * Date: 13-5-6
 * Time: 下午12:29
 * To change this template use File | Settings | File Templates.
 */
public class UserManageTest {
    @Test
    public void testUserManage(){
        Mockery mockery= new Mockery();
        final UserService userService=mockery.mock(UserService.class);
        final String message="abin";
        final String expectValue="hello abin";
         mockery.checking(new Expectations(){{
             oneOf(userService).getMessage(message);
             will(returnValue(expectValue));
         }});
        String actual=userService.getMessage(message);
        System.out.println("actual="+actual);
        TestCase.assertEquals(expectValue,actual);
        mockery.assertIsSatisfied();
    }
}








第二部分:JMOCK测试普通类

package com.abin.lee.mock.jmock;

/**
 * Created with IntelliJ IDEA.
 * User: abin
 * Date: 13-5-6
 * Time: 下午12:43
 * To change this template use File | Settings | File Templates.
 */
public class UserManage {
    public String getMessage(String message){
       String result="hello "+message;
        System.out.println("result="+result);
        return result;
    }
}

 






package com.abin.lee.mock.jmock;

import junit.framework.TestCase;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Test;

/**
 * Created with IntelliJ IDEA.
 * User: abin
 * Date: 13-5-6
 * Time: 下午12:47
 * To change this template use File | Settings | File Templates.
 */
public class UserManageTest {
    @Test
    public void testUserManage(){
        Mockery mockery=new Mockery();
        mockery.setImposteriser(ClassImposteriser.INSTANCE);
        final UserManage userManage=mockery.mock(UserManage.class);
        final String message="abin";
        final String expectValue="hello abin";
        mockery.checking(new Expectations(){{
            oneOf(userManage).getMessage(message);
            will(returnValue(expectValue));
        }});
        String expect=userManage.getMessage(message);
        System.out.println("expect="+expect);
        TestCase.assertEquals(expectValue,expect);
        mockery.assertIsSatisfied();
    }
}







posted @ 2013-05-06 12:42 abin 阅读(601) | 评论 (0)编辑 收藏

实例一:

package com.abin.lee.async;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.reactor.IOReactorException;
import org.junit.Test;

import java.io.IOException;
import java.util.concurrent.Future;

/**
 * Created with IntelliJ IDEA.
 * User: abin
 * Date: 13-4-23
 * Time: 下午6:13
 * To change this template use File | Settings | File Templates.
 */
public class HttpAsyncClientTest {
    private static final String HttpUrl="http://localhost:8100/MyThread/HttpClientPostProxyServlet";
    @Test
    public void testHttpAsyncClient() throws IOException {
         HttpAsyncClient httpAsyncClient=new DefaultHttpAsyncClient();
         httpAsyncClient.start();
        HttpPost request=null;
        try {
            request=new HttpPost(HttpUrl);
            Future<HttpResponse> future=httpAsyncClient.execute(request,null);
            HttpResponse response=future.get();
            System.out.println("response="+response);
        }catch(Exception e){
             e.printStackTrace();
        }finally {
            if(!request.isAborted()){
                request.abort();;
            }
            httpAsyncClient.getConnectionManager().shutdown();
        }

    }
}








实例二:

package com.abin.lee.async;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.client.HttpAsyncClient;
import org.junit.Test;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;

/**
 * Created with IntelliJ IDEA.
 * User: abin
 * Date: 13-4-23
 * Time: 下午6:13
 * To change this template use File | Settings | File Templates.
 */
public class HttpAsyncClientFutureCallBackTest {
    private static final String HttpUrl="http://localhost:8100/MyThread/HttpClientGetProxyServlet";
    private static final String HttpOneUrl="http://localhost:8100/MyThread/HttpClientGetOneServlet";
    private static final String HttpTwoUrl="http://localhost:8100/MyThread/HttpClientGetTwoServlet";
    @Test
    public void testHttpAsyncClientFutureCallBack() throws IOException {
         HttpAsyncClient httpAsyncClient=new DefaultHttpAsyncClient();
         httpAsyncClient.start();
        HttpGet[] requests=null;
        try {
            requests=new HttpGet[]{new HttpGet(HttpUrl),new HttpGet(HttpOneUrl),new HttpGet(HttpTwoUrl)};
            final CountDownLatch latch=new CountDownLatch(requests.length);
            for(final HttpGet request:requests){
                httpAsyncClient.execute(request,new FutureCallback<HttpResponse>() {
                    @Override
                    public void completed(HttpResponse httpResponse) {
                        latch.countDown();
                        System.out.println(request.getRequestLine()+"--->"+httpResponse.getStatusLine());
                        //To change body of implemented methods use File | Settings | File Templates.
                    }

                    @Override
                    public void failed(Exception e) {
                        latch.countDown();
                        System.out.println(request.getRequestLine()+"-->"+e.getMessage());
                        //To change body of implemented methods use File | Settings | File Templates.
                    }

                    @Override
                    public void cancelled() {
                        latch.countDown();
                        System.out.println(request.getRequestLine()+"--->"+" cancelled");
                         //To change body of implemented methods use File | Settings | File Templates.
                    }
                }) ;
            }
            latch.await();
            System.out.println("shutting down");
        }catch(Exception e){
             e.printStackTrace();
        }finally {
            httpAsyncClient.getConnectionManager().shutdown();
        }

    }
}

posted @ 2013-04-28 16:26 abin 阅读(2371) | 评论 (0)编辑 收藏

在多线程设计中,我猜常常会遇到线程间相互等待以及某个线程等待1个或多个线程的场景,比如多线程精密计算和大量数据处理,这里写下我自己的体会和理解。

   

    我想应该有很多办法,如果是简单的1:1关系,那么可以wait()和notify()解决,就像一把锁和一把钥匙;如果是1:N关系,这个1就需要关心N的所有状态了,最笨的办法是1可以去查看N当前的状态,轮询询问工作是否做完。而好点的办法是N做完后主动告诉1,然后N就会有2种选择,要么听从1的命令,要么继续干自己其他的活。

 

    用传统的方法我想应该是都能实现的,而JDK1.5提供了CyclicBarrier与CountDownLatch来解决了这两个问题,而她们的区别是:

    CyclicBarrier使所有线程相互等待,而CountDownLatch使一个或多个线程等待其他线程。区别类似上面蓝色字体,CountDownLatch不会等待其他线程了,只要做完自己的工作就干自己的活去了,也就是run()方法里其他的任务。

 

Example:

 

 

public static void testCountDownLatch() throws InterruptedException{   
  CountDownLatch cdl
=new CountDownLatch(2);   
  ExecutorService exe
=Executors.newFixedThreadPool(2);   
   
class Bow implements  Runnable{   
    CountDownLatch cdl;   
    
public Bow(CountDownLatch cdl){   
    
this.cdl=cdl;    
    }
   
    
public void run(){   
     System.out.println(
"The bow is coming");   
     System.out.println(
"kick a bow ");   
     
this.cdl.countDown();   
     System.out.println(
"do other thing");   
     }
   
   }
   
  exe.execute(
new Bow(cdl));   
  exe.execute(
new Bow(cdl));   
  exe.shutdown();   
  System.out.println(
"Wait");   
    cdl.await();   
    System.out.println(
"End..");   
    
 }
   
  
    
public static void main(String[] args) {   
        
try {   
            Test.testCountDownLatch();   
        }
 catch (InterruptedException e) {   
        }
   
    }
  

 

输出的结果为:

 

The bow is coming
kick a bow
do other thing
Wait...
The bow is coming
kick a bow
do other thing
End..

 

如上所说do other thing不受影响。

 

写了一个CyclicBarrier的例子:

 

public static void testCyclicBarrier() throws InterruptedException, BrokenBarrierException{
        CyclicBarrier barr
=new CyclicBarrier(2+1);
        
        ExecutorService exe
=Executors.newFixedThreadPool(2);
         
class Bow implements  Runnable{
             CyclicBarrier barr;
                
public Bow(CyclicBarrier barr){
                
this.barr=barr;    
                }

                
public void run(){
                    System.out.println(
"The bow is coming");
                    System.out.println(
"kick a down");
                    
try {
                        barr.await();
                    }
 catch (InterruptedException e) {
                        
// TODO Auto-generated catch block
                        e.printStackTrace();
                    }
 catch (BrokenBarrierException e) {
                        
// TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                    System.out.println(
"do other thing");
                    }

            }

        exe.execute(
new Bow(barr));
        exe.execute(
new Bow(barr));
        exe.shutdown();
        System.out.println(
"Wait");
        barr.await();
       System.out.println(
"End..");
    
    }



    
public static void main(String[] args) {
        
try {
            Test.testCyclicBarrier();
        }
 catch (InterruptedException e) {
        }

        
catch (BrokenBarrierException e) {
        }

    }

 

输出结果为:

 

Wait...
The bow is coming
kick a down
The bow is coming
kick a down
do other thing
End..
do other thing

 

总结:

我们看到do other thing被阻塞了,直到最后才执行,可见,栅栏和计数器的目完全不同了。向Doug Lea牛人学习:)

 









在网上看到很多人对于CountDownLatch和CyclicBarrier的区别简单理解为CountDownLatch是一次性的,而CyclicBarrier在调用reset之后还可以继续使用。那如果只是这么简单的话,我觉得CyclicBarrier简单命名为ResetableCountDownLatch好了,显然不是的。
我的理解是,要从他们的设计目的去看这两个类。javadoc里面的描述是这样的。

CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

CyclicBarrier : A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.

可能是我的英语不够好吧, 我感觉从这个javadoc里面要准确理解他们的差异还是不容易的。
我的理解是

CountDownLatch : 一个线程(或者多个), 等待另外N个线程完成某个事情之后才能执行。   CyclicBarrier        : N个线程相互等待,任何一个线程完成之前,所有的线程都必须等待。
这样应该就清楚一点了,对于CountDownLatch来说,重点是那个“一个线程”, 是它在等待, 而另外那N的线程在把“某个事情”做完之后可以继续等待,可以终止。而对于CyclicBarrier来说,重点是那N个线程,他们之间任何一个没有完成,所有的线程都必须等待。



CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.
而CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流.

posted @ 2013-04-28 15:37 abin 阅读(447) | 评论 (0)编辑 收藏

查看oracle表结构:
desc ABIN_LEE;
select * from user_tab_columns where table_name='ABIN_LEE';
select dbms_metadata.get_ddl('TABLE','ABIN_LEE') from dual;
select * from cols where table_name= 'ABIN_LEE';





posted @ 2013-04-25 14:29 abin 阅读(439) | 评论 (0)编辑 收藏

//EasyMockServlet.java
package com.abin.lee.easymock.servlets;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* Created with IntelliJ IDEA.
* User: abin
* Date: 13-4-22
* Time: 下午3:12
* To change this template use File | Settings | File Templates.
*/
public class EasyMockServlet extends HttpServlet {
    public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
        System.out.println("doPost come in");
        String userName=request.getParameter("userName");
        String passWord=request.getParameter("passWord");
        System.out.println("userName="+userName+",passWord="+passWord);
        if("abin".equals(userName)&&"varyall".equals(passWord)){
            System.out.println("come in");
            ServletContext context=this.getServletContext();
            RequestDispatcher dispatcher=context.getNamedDispatcher("dispatcher");
            dispatcher.forward(request,response);
        }else{
            throw new RuntimeException("Login failed.");
        }
    }

}





//EasyMockServletFailedTest.java
package com.abin.lee.easymock.servlets;

import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Test;

import javax.servlet.http.HttpServletRequest;

import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.fail;

/**
* Created with IntelliJ IDEA.
* User: abin
* Date: 13-4-22
* Time: 下午5:08
* To change this template use File | Settings | File Templates.
*/
public class EasyMockServletFailedTest {
    @Test
    public void testEasyMockServletFailed(){
        HttpServletRequest request=EasyMock.createMock(HttpServletRequest.class);
        EasyMock.expect(request.getParameter("userName")).andReturn("abin");
        EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").times(1);
        EasyMock.replay(request);
        EasyMockServlet easyMockServlet=new EasyMockServlet();
        try {
              easyMockServlet.doPost(request,null);
              fail("Not caught exception!");
        }catch(Exception e){
            assertEquals("Login failed.", e.getMessage());
            e.printStackTrace();
        }
        EasyMock.verify(request);
    }
}






//EasyMockServletSuccessTest
package com.abin.lee.easymock.servlets;

import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.junit.Test;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
* Created with IntelliJ IDEA.
* User: abin
* Date: 13-4-22
* Time: 下午7:49
* To change this template use File | Settings | File Templates.
*/
public class EasyMockServletSuccessTest {
    @Test
    public void testEasyMockServletSuccess() throws ServletException, IOException {
        IMocksControl control= EasyMock.createControl();
        HttpServletRequest request=control.createMock(HttpServletRequest.class);
//        HttpServletResponse response=control.createMock(HttpServletResponse.class);
        final ServletContext servletContext=control.createMock(ServletContext.class);
        RequestDispatcher requestDispatcher=control.createMock(RequestDispatcher.class);

        EasyMock.expect(request.getParameter("userName")).andReturn("abin").once();
        EasyMock.expect(request.getParameter("passWord")).andReturn("varyall").once();
        EasyMock.expect(servletContext.getNamedDispatcher("dispatcher")).andReturn(requestDispatcher).times(1);

        requestDispatcher.forward(request,null);
        EasyMock.expectLastCall();

        control.replay();

        EasyMockServlet easyMockServlet=new EasyMockServlet(){
           public ServletContext getServletContext(){
               return servletContext;
           }
        } ;

        easyMockServlet.doPost(request,null);
        control.verify();


    }
}
posted @ 2013-04-23 13:27 abin 阅读(747) | 评论 (0)编辑 收藏

仅列出标题
共50页: First 上一页 12 13 14 15 16 17 18 19 20 下一页 Last