您的位置:首页 > 大数据 > 人工智能

使用wait、notify简单实现并行计算

2016-03-26 22:41 387 查看
jdk1.5之后可以使用 Executor、Callable和Future实现多个线程协同工作。

比如有这样的场景:需要从3个数据库中分别查询数据,最后合并结果返回。

如果不用多线程的话,只能先查第1个库,查完放在List中,接着再查第2个库,接着再查第3个库,类似的代码可能是这样的:

List<T> result1 = selectDB1();
List<T> result2 = selectDB2();
List<T> result3 = selectDB3();
// 合并结果返回
result1.addAll(result2);
result1.addAll(result3);


这里selectDB1()、selectDB谐()和selectDB3() 完全可以并行执行,他们之间没有依赖关系,如果我们用3个线程并行地去调用这3个方法,3个方法都有结果返回后再合并,则在多核的环境下应该可以得到更好的查询速度。

而在jdk1.5之前没有 Executor、Callable和Future,那我们如果使用多线程来实现并行计算呢?

下面的代码演示了使用3个线程来并行计算从1累加到300000000L之和。

test3Thread()用3个线程来计算,test1Thread() 只用一个线程来计算,比较下来 test3Thread()比test1Thread()快1倍。

public class TestMoreThread {

/**
* 只用一个线程计算
*/
public static void test1Thread(){
long result = 0L;
for(long i=0;i<300000000L;i++){
result += i;
}
}

/**
* 使用3个线程计算
*/
public static void test3Thread(){
Object lock = new Object();
//启动3个线程分成3断同时计算
Computer c1 = new Computer("T1", lock, 0, 100000000L);
Computer c2 = new Computer("T2", lock, 100000001L, 200000000L);
Computer c3 = new Computer("T3", lock, 200000001L, 300000000L);

new Thread(c1).start();
new Thread(c2).start();
new Thread(c3).start();
// 判断3个线程是否都计算完成
while (!c1.getStatus() || !c2.getStatus() || !c3.getStatus()) {
synchronized (lock) {
try {
// 在这里释放锁和CUP控制权,当有子线程的状态改变后会唤配它继续执行
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 在这里合并3个线程的计算结果
System.out.println((c1.getResult()+c2.getResult()+c3.getResult()));
}

public static void main(String[] args) {
long begin = System.currentTimeMillis();
test3Thread();
System.out.println("Take me for "+(System.currentTimeMillis()-begin)+" ms");
}
}

/**
* 执行子任务的子线程
* @author bruce
*
*/
class Computer implements Runnable {
private boolean status = false;
private long result;
private Object lock;
private String name;
private long begin;
private long end;

public Computer(String name, Object lock, long begin, long end) {
this.begin = begin;
this.end = end;
this.lock = lock;
this.name = name;
}

@Override
public void run() {
long sum = 0;
for (long i = begin; i <= end; ++i) {
sum += i;
}
this.result = sum;
this.status = true;
//计算完后唤醒主线程
synchronized (lock) {
lock.notify();
}
System.out.println(name+":"+sum);
}

public long getResult(){
return this.result;
}

public boolean getStatus(){
return this.status;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: