zoukankan      html  css  js  c++  java
  • 多线程排序

    import java.util.*;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;

    public class SortMain {

    public static void main(String[] args) throws Exception{
    Integer threadNumber = 4; //线程数量
    Integer stopNumber = threadNumber; //闭合器数量
    Integer randomCount = 50; //随机数数量
    Integer randomNumber = 50; //随机数范围
    List<Integer> workSpeace = new ArrayList<>(); //每个线程需要工作的量 list的长度与线程量一样
    if(randomCount % threadNumber == 0){
    for(int i=0; i < threadNumber; i ++){
    workSpeace.add(randomCount/threadNumber);
    }
    }else{
    Integer itemValue = randomCount/threadNumber;
    for(int i = 0 ; i < threadNumber ; i ++){
    if(i == threadNumber -1){
    workSpeace.add((randomCount-(itemValue*threadNumber)) + itemValue);
    }else{
    workSpeace.add(itemValue);
    }
    }
    }
    CountDownLatch countDownLatch = new CountDownLatch(stopNumber); //闭合器子线程闭合器

    CountDownLatch countDownLatchMain = new CountDownLatch(stopNumber); //主线程闭合器

    ExecutorService executors = Executors.newFixedThreadPool(threadNumber); //线程池
    Lock lock = new ReentrantLock();
    List<Integer> arrayList = new ArrayList<>();
    Random random = new Random(System.currentTimeMillis());
    try {
    for(int i=0; i < randomCount ; i++){
    arrayList.add(random.nextInt(randomNumber));
    }
    System.out.println("随机数集合:"+arrayList +" 长度:"+arrayList.size());
    Map<Integer, String> thradValueMap = Collections.synchronizedMap(new HashMap());
    Map<Integer, List<Integer>> mainValueMap = Collections.synchronizedMap(new HashMap());
    List countSizeListValue = new ArrayList(); //
    for(int i =0; i <threadNumber; i ++){
    int finalI = i;
    executors.execute(new Runnable() {
    @Override
    public void run(){
    List<Integer> paramsList = new ArrayList(); //每个线程工作的内容
    //思路:每个线程干10个值,10个线程干100个值
    int startIndex; //没个线程工作的10个值的尾坐标,也是没个线程管理数值的结束 //startIndex endThreadIndex 因为for循环是反着的,所以这个值也是反着的
    int endThreadIndex; //没个线程工作的10个值的头坐标,也是没个线程管理数值的开始
    endThreadIndex = ((randomCount/threadNumber)*finalI);
    if(finalI == threadNumber-1){
    startIndex = ((randomCount - ((randomCount/threadNumber)*finalI)) + endThreadIndex) -1;
    }else{
    startIndex = endThreadIndex + ((randomCount/threadNumber)-1);
    }
    for(int forStartIndex = startIndex; forStartIndex >= endThreadIndex; forStartIndex--){
    paramsList.add(arrayList.get(forStartIndex)); //通过循环拿到每个线程需要工作的内容
    }
    //由于已知随机数最大的值是100,所以可以很容易的规范没个线程所管理的值范围,在这里暂定 1号线程工作范围为0-10.2号线程为11-20,以此类推
    //start 此代码块规定此线程管理值的区间
    int theManageValueMax;
    int theManageValueMin;
    if(finalI == threadNumber-1){//9
    theManageValueMax = startIndex+1;
    theManageValueMin = endThreadIndex;
    }else{
    theManageValueMax = startIndex;
    theManageValueMin = endThreadIndex;
    }
    List<Integer> discardValue = new ArrayList<>(); //需要剔除的值的集合
    for(int chickIndex = 0; chickIndex < workSpeace.get(finalI); chickIndex++){ //循环判断每个线程需要工作内容值
    Integer workValue = paramsList.get(chickIndex); //每个线程工作的基本单位(数值)
    if(theManageValueMin <= workValue&&workValue <= theManageValueMax){
    //如果符合工作数值区间,则什么都不做;
    continue;
    }else{ //如果不符合工作区间,则剔除到公共区域
    Integer thisNumberParent = -1;
    try {
    lock.lockInterruptibly();
    thisNumberParent = chickNumberParent(threadNumber, randomNumber, workValue); //调用此方法判断此随机数属于哪个线程的工作区间
    }catch (Exception e){
    for(StackTraceElement itemError : e.getStackTrace()){
    System.out.println(itemError);
    }
    }finally {
    lock.unlock();
    }
    String theValueByMap = thradValueMap.get(thisNumberParent);
    if(theValueByMap == null || "".equals(theValueByMap)){
    thradValueMap.put(thisNumberParent,workValue.toString());
    }else{
    thradValueMap.put(thisNumberParent,theValueByMap + ","+workValue.toString());
    }
    discardValue.add(workValue);
    }
    }
    for(Integer itemDiscardvalue :discardValue){
    paramsList.remove(new Integer(itemDiscardvalue.intValue()));
    }
    countDownLatch.countDown();
    try {
    countDownLatch.await();
    String thisThreadWorkValue = thradValueMap.get(finalI); //当所有子线程工作完之后 从公共区域拿出本应该属于自己的值
    if(thisThreadWorkValue == null || "".equals(thisThreadWorkValue)){ //如果公共区域没有属于自己的工作值

    }else {
    String thisThreadWorkValueSz[] = thisThreadWorkValue.split(",");
    for(int i=0; i < thisThreadWorkValueSz.length; i++){
    paramsList.add(Integer.valueOf(thisThreadWorkValueSz[i]));
    }
    paramsList = sortInt(paramsList);
    }
    mainValueMap.put(finalI,paramsList);
    }catch (Exception e){
    e.fillInStackTrace();
    }finally {
    countDownLatchMain.countDown();
    }
    // System.out.println("分割线---------------------------------");
    }
    });
    }
    countDownLatchMain.await();
    List<Integer> finalList = new ArrayList<>();
    for(int i =0; i<threadNumber; i++){
    List<Integer> itemList = mainValueMap.get(i);
    if(itemList == null || itemList.isEmpty()){
    continue;
    }
    for(Integer itemValue : itemList){
    finalList.add(itemValue);
    }
    }
    System.out.println("排序好的值:"+finalList+" 长度:"+finalList.size());
    arrayList.removeAll(finalList);
    System.out.println("差集为:"+arrayList);
    }catch (Exception e){
    for(StackTraceElement itemError :e.getStackTrace()){
    System.out.println(itemError);
    }
    }finally {
    executors.shutdownNow();
    }

    }


    /**
    *
    * @param paramsList 每个线程要干的事情...排序
    * @return
    */
    private static List<Integer> sortInt(List<Integer> paramsList){
    List<Integer> resutList = new LinkedList<>();
    for(int paramsListIndex = 0 ; paramsListIndex <paramsList.size(); paramsListIndex++){
    if(resutList.size() == 0){
    resutList.add(paramsList.get(paramsListIndex));
    continue;
    }
    for(int resultListIndex = resutList.size(); resultListIndex >= 0 ; resultListIndex--){
    if(resultListIndex == 0){
    resutList.add(resultListIndex,paramsList.get(paramsListIndex));
    break;
    }
    int paramsListInt = paramsList.get(paramsListIndex).intValue();
    int resultListInt = resutList.get(resultListIndex-1).intValue();
    if(paramsListInt <= resultListInt){
    continue;
    }else{
    resutList.add(resultListIndex,paramsList.get(paramsListIndex));
    break;
    }
    }
    }

    return resutList;
    }

    /**
    * 判断该数值在map中的key应该是多少
    * @param threadNumber 线程量
    * @param randomNumber 随机数范围
    * @param needChickNumber 需要判断的值
    * @return
    */
    private static Integer chickNumberParent(Integer threadNumber,Integer randomNumber,Integer needChickNumber){
    Integer onlyThreadNumber = randomNumber/threadNumber; //单个线程负责值得区间, 比如 93个随机数 6个线程, 那么93/6 就是前五个的线程负责量,余数是最后一个线程负责量
    Integer valueIndex = needChickNumber / onlyThreadNumber; //还以上一行注释为例子, 如果现在需要判断93这个值属于哪个线程的工作区间,则 93/(随机数数量/线程量) 93/15 = 6, 因为线程量一共为6,在list中长度最大值为5(因为list坐标从0开始),所以93这个值属于最后一个线程的工作区间
    if(valueIndex >= threadNumber){
    return valueIndex-1;
    }else{
    return valueIndex;
    }
    }


    }
  • 相关阅读:
    来看看面试必问的HashMap,一次彻底帮你搞定HashMap源码
    深入浅出!springboot从入门到精通,实战开发全套教程!
    讲一讲Java的字符串常量池,看完你的思路就清晰了
    面向对象的这些核心技术,你掌握后包你面试无忧
    他凭借这70份PDF,3170页文件,成功斩获了含BATJ所有的offer
    springboot实战开发全套教程,让开发像搭积木一样简单!Github星标已上10W+!
    这行代码告诉你!为什么你地下城与勇士(DNF)的装备强化老是失败?
    精益求精!Spring Boot 知识点全面回顾,带你重新细读源码!
    太妙了!Spring boot 整合 Mybatis Druid,还能配置监控?
    putchar(".:-=+*#%@"[(int)(d * 5.0f)])
  • 原文地址:https://www.cnblogs.com/llja/p/10620335.html
Copyright © 2011-2022 走看看