线程笔记之并发同步(三)

2014-11-24 01:34:22 · 作者: · 浏览: 1
);
} finally {
monitor.countDown(); //计数器-1
}
}
});

t1.start();
t2.start();

monitor.await(1, TimeUnit.SECONDS); //monitor.await(1000, TimeUnit.MILLISECONDS); 设定超时阀值
//线程1/2都已返回,需要验证结果

long s3 = System.currentTimeMillis();

System.out.println("time cost for normal execution:" + (s2 - s1));
System.out.println("time cost for concurrent execution:" + (s3 - s2));
}


方式3:使用JDK5中新的线程实现方式和线程池


Java代码
public static void main(String[] args) throws InterruptedException, ExecutionException {
final ExecutorService execPool = Executors.newFixedThreadPool(5);
final ConcurrentSimpleTest3 cst = new ConcurrentSimpleTest3();

long s1 = System.currentTimeMillis();
cst.method1();
cst.method2();
long s2 = System.currentTimeMillis();

Callable call1 = new Callable(){
@Override
public Void call() throws Exception {
cst.method1();
return null;
}
};

Callable call2 = new Callable(){
@Override
public Void call() throws Exception {
cst.method2();
return null;
}
};

Future task1 = execPool.submit(call1);
Future task2 = execPool.submit(call2);

task1.get();//task1.get(1, TimeUnit.SECONDS); get方法会阻塞,直到线程执行结束返回结果或者超时
task2.get();//task2.get(1, TimeUnit.SECONDS);

//线程1/2都已返回,需要验证结果

long s3 = System.currentTimeMillis();

System.out.println("time cost for normal execution:" + (s2 - s1));
System.out.println("time cost for concurrent execution:" + (s3 - s2));

execPool.shutdown();
}

要达到目的,我们的实现的方式有多种,上面给出的例子也只是抛砖引入,那么该如何抉择呢?个人认为应该考虑以下几个方面:

并发线程(任务)的可控性。如线程执行是否超时,可中断执行中的线程,异常处理以及获取线程执行的状态等。方法1/2/3都针对具体的子线程(任务)可控,而方法2在超时设定方面则是针对并发的线程。
合理性,即合乎人的思维和设计,个人认为用信号量同步的方式(方法2)比较合理。
高效性,即性能。线程池应该是个不错的选择。
简化性,即实现和使用比较简单化。
简化,其实就是更多的复用/重用。对于上面给出的应用场景,可以提出下面这样的模型:

\
其中主线程为main thread,在它的执行过程中会启动2个子线程T1和T2,等待T1和T2执行结束后,main thread才能执行结束。

进一步抽象下,便可以得到下面这个复杂点的模型:

\
模型中每个背景为白色的节点代表一个Thread,边代表执行的步骤和方向。

Begin 会启动T1和T2 线程,T2 执行完毕后会执行T4,而从 T1 和 T2 指向 T3 的两条边表示的是 T3 必须等 T1 和 T2 都执行完毕以后才能开始执行。若T1和T2同时执行完毕,那么T3和T4也会并发执行。当T3和T4执行完成,就会执行End,整个过程结束。

对于这个模型,我们可以提供一个简单的框架示意图:

\

其具体实现主要分为3部分:

Constructor: 线程(任务)构建器,主要构建子线程(任务)以及其关联关系(主要是前置依赖关系)
Executor: 线程(任务)执行器,主要负责高效地执行所提交的线程(任务)
Monitor: 负责监控一组线程(任务)的执行状态并进行简单地调度。如前置任务出现异常,那么后续任务该任何执行等等
当然还得提供一些额外的访问接口:如,线程(任务)的执行结果等。这样一个框架/组件的雏形就有了,而作为调用者,也只要关心输入和输出即可。



总结:本文主要从一个顺序调用的例子出发,因性能问题引申到了并发,列出了并发同步的几种简单实现示例,并最后提出了一个并发框架的雏形。

有兴趣的朋友可以一起讨论其具体实现和应用。

--《全文完》--