多线程最典型的需求场景一般是:有的时候为了获取性能,需要各个业务并行获取并处理数据,同时返回处理好的数据,这时候多线程就派上用处了。
对这个场景,最简单的代码实现是可以使用CyclicBarrier或CountDownLatch;
话不多说,直接上代码:
测试主类-MainThread:
import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; /** * shiroexample * functional describe: * * @author DR.YangLong [[email protected]] * @version 1.0 2015/4/13 9:22 */ public class MainThread extends Thread{ private Map<String,Object> resultMap; public MainThread(Map<String, Object> resultMap) { this.resultMap = resultMap; } @Override public void run() { System.out.println("实验2到主线程了,取出结果:"); Iterator<String> iterator=resultMap.keySet().iterator(); while (iterator.hasNext()){ String name=iterator.next(); System.out.println("线程:" + resultMap.get(name)); } System.out.println("实验2等待线程结束。"); } public static void main(String[] args){ /*** * 障碍器测试 */ Map<String,Object> resultMap=new ConcurrentHashMap<String, Object>(6); CyclicBarrier cyclicBarrier=new CyclicBarrier(5);//实验1:主线等待其他线程 //CyclicBarrier cyclicBarrier=new CyclicBarrier(4,new MainThread(resultMap));//实:2:一般性并行其他线程执行完执行某个线程。 new ThreadService("CyclicBarrier服务1",cyclicBarrier,resultMap).start(); new ThreadService("CyclicBarrier服务2",cyclicBarrier,resultMap).start(); new ThreadService("CyclicBarrier服务3",cyclicBarrier,resultMap).start(); new ThreadService("CyclicBarrier服务4",cyclicBarrier,resultMap).start(); //以下为实验1内容,实验2时注释掉 try { System.out.println("当前线程等待其他线程"); cyclicBarrier.await(); System.out.println("当前等待结束,开始执行,取出结果:"); Iterator<String> iterator=resultMap.keySet().iterator(); while (iterator.hasNext()){ String name=iterator.next(); System.out.println("线程:" + resultMap.get(name)); } System.out.println("当前线结束。"); } catch (Exception e) { e.printStackTrace(); } /*** * 计数数器测试 */ resultMap.clear(); CountDownLatch countDownLatch=new CountDownLatch(4); new CountDownService("CountDownLatch服务A",countDownLatch,resultMap).start(); new CountDownService("CountDownLatch服务B",countDownLatch,resultMap).start(); new CountDownService("CountDownLatch服务C",countDownLatch,resultMap).start(); new CountDownService("CountDownLatch服务D",countDownLatch,resultMap).start(); try { System.out.println("CountDownLatch当前线程等待。"); countDownLatch.await();//等待并行线程完成工作 System.out.println("CountDownLatch当前线程等待结束,开始执行,取出结果:"); Iterator<String> iterator=resultMap.keySet().iterator(); while (iterator.hasNext()){ String name=iterator.next(); System.out.println("线程:" + resultMap.get(name)); } System.out.println("CountDownLatch当前线程结束。"); } catch (InterruptedException e) { e.printStackTrace(); } } }
CyclicBarrier 测试使用的service,ThreadService:
import java.util.Map; import java.util.concurrent.CyclicBarrier; /** * shiroexample * functional describe: * * @author DR.YangLong [[email protected]] * @version 1.0 2015/4/13 9:12 */ public class ThreadService extends Thread{ private String name; private CyclicBarrier cyclicBarrier; private Map<String,Object> resultMap; public ThreadService(String name, CyclicBarrier cyclicBarrier,Map<String,Object> resultMap) { this.name = name; this.cyclicBarrier = cyclicBarrier; this.resultMap=resultMap; } @Override public void run() { System.out.println("子线程"+this.name+"正在执行!"); try { resultMap.put(this.name,this.name); Thread.sleep(1000); System.out.println("子线程"+this.name+"执行完成!"); cyclicBarrier.await();//计数器-1 //添加日志等操作在下面,当计数器为0时执行 } catch (Exception e) { e.printStackTrace(); } } }
CountDownLatch 测试使用Service CountDownService:
import java.util.Map; import java.util.concurrent.CountDownLatch; /** * shiroexample * functional describe: * * @author DR.YangLong [[email protected]] * @version 1.0 2015/4/13 10:01 */ public class CountDownService extends Thread{ private String name; private CountDownLatch countDownLatch; private Map<String,Object> resultMap; public CountDownService(String name, CountDownLatch countDownLatch,Map<String,Object> resultMap) { this.name = name; this.countDownLatch = countDownLatch; this.resultMap=resultMap; } @Override public void run() { System.out.println("子线程" + this.name + "正在执行!"); try { resultMap.put(this.name,this.name); Thread.sleep(1000); System.out.println("子线程"+this.name+"执行完成!"); countDownLatch.countDown();//计数器-1 //添加日志等操作在下面,当计数器为0时执行 } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
当前线程等待其他线程 子线程CyclicBarrier服务1正在执行! 子线程CyclicBarrier服务2正在执行! 子线程CyclicBarrier服务3正在执行! 子线程CyclicBarrier服务4正在执行! 子线程CyclicBarrier服务1执行完成! 子线程CyclicBarrier服务4执行完成! 子线程CyclicBarrier服务3执行完成! 子线程CyclicBarrier服务2执行完成! 当前等待结束,开始执行,取出结果: 线程:CyclicBarrier服务4 线程:CyclicBarrier服务1 线程:CyclicBarrier服务3 线程:CyclicBarrier服务2 当前线结束。 CyclicBarrier服务1日志处理...... CyclicBarrier服务4日志处理...... CyclicBarrier服务3日志处理...... CyclicBarrier服务2日志处理...... CountDownLatch当前线程等待。 子线程CountDownLatch服务A正在执行! 子线程CountDownLatch服务B正在执行! 子线程CountDownLatch服务C正在执行! 子线程CountDownLatch服务D正在执行! 子线程CountDownLatch服务A执行完成! 子线程CountDownLatch服务B执行完成! CountDownLatch服务A日志处理...... CountDownLatch服务B日志处理...... 子线程CountDownLatch服务D执行完成! CountDownLatch服务D日志处理...... 子线程CountDownLatch服务C执行完成! CountDownLatch服务C日志处理...... CountDownLatch当前线程等待结束,开始执行,取出结果: 线程:CountDownLatch服务A 线程:CountDownLatch服务D 线程:CountDownLatch服务B 线程:CountDownLatch服务C CountDownLatch当前线程结束。
对于数据的取回,有2个方式,一个是使用单例的容器,另外一个是定义成属性,提供getter方法,运行完成后调用获取,但这又涉及到这2者的区别:
CyclicBarrier 阻塞所有调用await()的线程,等待计数器为0,所有线程【包括一个目标线程】才全部一起往下执行。
CountDownLatch 不阻塞所有线程【countDown()的线程不会被阻塞】,只阻塞调用await()的线程,当计数器为0时调用await()的线程继续往下执行。
所以,需要返回值在线程阻塞前完成封装,以确保主线程能够获得已完成封装的返回值。