一种父线程阻塞等待子线程的有效方法

       最近在做一个查询优化时,考虑到一次查询耗时较多,所以打算用多线程来做,之前是串行查询。比如一个用户查询触发50个线程,在只有一个用户的情况下,性能比串行查询确实提高了许多,但当多个用户同时触发查询的时候,CPU却飙高得很厉害,比串行查询好不了多少。

       因为一次查询是同步查询,即要等待所有的线程完成后才返回结果,所以一开始想到的办法是每次查询都起一个线程池,这个线程池里面有50个线程,这个线程池阻塞等待所有的线程完成然后返回结果,从而造成50个用户同时查询时起了50个线程池,cpu资源消耗殆尽。能不能做到所用用户查询触发的线程统一由一个线程池控制呢?百度后终于找到了解决办法。

 1 import java.util.concurrent.CountDownLatch;
 2 
 3 public class ThreadA implements Runnable {
 4 
 5     private CountDownLatch cDownLatch;
 6 
 7     private String name;
 8 
 9     public ThreadA(CountDownLatch cDownLatch, String threadName) {
10         this.cDownLatch = cDownLatch;
11         this.name = threadName;
12     }
13 
14     @Override
15     public void run() {
16         System.out.println(name + " begin.");
17         try {
18             Thread.sleep(500);
19         } catch (InterruptedException e) {
20             e.printStackTrace();
21         }
22         System.out.println(name + " end.");
23         cDownLatch.countDown();
24     }
25 }
线程执行体
 1 import java.util.concurrent.BlockingQueue;
 2 import java.util.concurrent.LinkedBlockingQueue;
 3 import java.util.concurrent.ThreadPoolExecutor;
 4 import java.util.concurrent.TimeUnit;
 5 
 6 public class MyThreadPool extends ThreadPoolExecutor {
 7 
 8     private static MyThreadPool myPool = new MyThreadPool(10, 100, 1,
 9             TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>());
10 
11     private MyThreadPool(int corePoolSize, int maximumPoolSize,
12             long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
13         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
14     }
15 
16     public static MyThreadPool getInstance() {
17         return myPool;
18     }
19 }
线程池
import java.util.concurrent.CountDownLatch;

public class MainThread {
    public static void main(String[] args) {
        ThreadExecutor executor = new ThreadExecutor("A", 3);
        executor.execute();
    }
}

class ThreadExecutor {
    private String prefix;
    private int size;

    public ThreadExecutor(String prefix, int size) {
        this.prefix = prefix;
        this.size = size;
    }

    public void execute() {
        System.out.println(prefix + " begin.");
        ThreadA temp = null;
        CountDownLatch cDownLatch = new CountDownLatch(size);
        for (int i = 0; i < size; i++) {
            temp = new ThreadA(cDownLatch, prefix + i);
            MyThreadPool.getInstance().execute(temp);
        }
        try {
            cDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(prefix + " end.");
    }
}
主线程

执行结果

A begin.
A0 begin.
A1 begin.
A2 begin.
A1 end.
A0 end.
A2 end.
A end.

 

posted @ 2013-06-23 00:05  涂墨留香  阅读(2571)  评论(0编辑  收藏  举报