一种父线程阻塞等待子线程的有效方法
最近在做一个查询优化时,考虑到一次查询耗时较多,所以打算用多线程来做,之前是串行查询。比如一个用户查询触发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.