多线程计算Java中的最小和最大数字

时间:2013-12-05 20:19:20

标签: java multithreading recursion

我编写了使用多线程计算给定数组中最小和最大数的代码。这个想法类似于binarysearch,我只是将数组分成两半并计算每一半的最小值和最大值,并相应地更新我的最小和最大字段。 这可能是用于多线程的愚蠢示例。但既然我想到了这一点,我想实现并看看它是如何发展的。到目前为止,代码SURPRISINGLY工作正确。我希望它不能给出正确的结果,因为我不是在等待第一个线程完成,而是立即关闭第二个线程。这意味着最小值和最大值不得正确更新。 有人可以指出为什么这在多次运行和任何改进空间都能正常工作。

代码在这里

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;



public class MinMax implements Runnable{

    Long min=Long.MAX_VALUE;
    Long max=Long.MIN_VALUE;
    int low;
    int high;
    Long[] arr;

    public  MinMax(int low, int high, Long[] arr){
        this.low = low;
        this.high=high;
        this.arr = arr;

    }
        @Override
        public void run() {
            System.out.println("called run ");
        if (low-high<=2){
            System.out.println("called ");
            List<Long> l = Arrays.asList(arr);
            min=Collections.min(l) < min ? Collections.min(l) : min;
            max=Collections.max(l) > max ? Collections.max(l) : max;
        }
        else {
                    System.out.println(Thread.currentThread());
            int mid = (high+low)/2;
            MinMax left = new MinMax(low,mid,arr);
            MinMax right = new MinMax(mid,high,arr);
            Thread t1 = new Thread(left);
            Thread t2 = new Thread(right);
            t1.start();
            t2.start();
            Set<Thread> threadset=Thread.getAllStackTraces().keySet();
             for (Thread t : threadset)
                 System.out.println(t.getName());
            try {
                t1.join();
                            t2.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }   
        }
    }

    public static void main(String[] args){
         long[] arr = {3,4,5,1123,567,78,90,5,35434,1,34,56,111,2,56,789,87645,343535};
         Long[] newarr= new Long[arr.length];
         int i = 0;
         for (long temp : arr)
             newarr[i++]=temp;
         MinMax m = new MinMax(0,arr.length,newarr);
         m.run();
         System.out.println(m.min);
         System.out.println(m.max);

    }

}

4 个答案:

答案 0 :(得分:3)

为什么会这样?第一次low 0high约为18low-high<=2为真,您的线程代码未被调用。无论如何,线程代码都不会产生任何结果。

ForkJoinPool旨在为您处理这类事情。

答案 1 :(得分:1)

我对您的代码的评论 - 首先,minmax需要声明为volatile,以确保它们的值在线程内及时更新。

然后,这个比较不是原子的,您可能需要将其包装到synchronized块中,或者如果AtomicInteger性能是compareAndSet,则可以考虑synchronized的{​​{1}} optmization不满意:

min=Collections.min(l) < min ? Collections.min(l) : min;
max=Collections.max(l) > max ? Collections.max(l) : max;

所以问题可能是两个线程同时计算它们的最小值,但是它们在不同的时间分配它,所以获胜者是谁的结果首先被写入。

正如@JamesKingsbery注意到你可能需要在第二个帖子上调用start()

可能是最后一件事,你可能不会在你的情况下获得任何性能提升,但这是一个很好的学习例子。

答案 2 :(得分:0)

为此使用RecursiveAction类。在这里,我使用RecursiveAction编写了程序。请找到以下代码。有关详细信息,请查看http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/RecursiveAction.html

package org.kavi.threadexample;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class MinMax extends RecursiveAction{

Long min=Long.MAX_VALUE;
Long max=Long.MIN_VALUE;
int low;
int high;
Long[] arr;

public  MinMax(int low, int high, Long[] arr){
    this.low = low;
    this.high=high;
    this.arr = arr;

}

@Override
protected void compute() {
     if (low-high<=2){
         System.out.println("called ");
         List<Long> l = Arrays.asList(arr);
         min=Collections.min(l) < min ? Collections.min(l) : min;
         max=Collections.max(l) > max ? Collections.max(l) : max;
     }
     else {
         int mid = (low + high) >>> 1;
         MinMax left = new MinMax(low, mid,arr );
         MinMax right = new MinMax(mid, high, arr);

     }
}


public static void main(String[] args){
     long[] arr = {3,4,5,1123,567,78,90,5,35434,1,34,56,111,2,56,789,87645,343535};
     Long[] newarr= new Long[arr.length];
     int i = 0;
     for (long temp : arr) {
         newarr[i++]=temp;
     }
     MinMax m = new MinMax(0,arr.length,newarr);
     ForkJoinPool pool = new ForkJoinPool();
     pool.invoke(m);
     System.out.println(m.min);
     System.out.println(m.max);

}

}

答案 3 :(得分:0)

@KaviK RecursiveAction示例的固定版本:

(KaviK版本中的错误包括未实际调用递归任务,未合并其结果以及一次计算整个集合的最小值/最大值,而不是进行任何实际尝试来细分任务)

#!/usr/bin/env bash

WORK_DIR=~/work_dir/
FOLDERS_TO_SEARCH=$(find $WORK_DIR -maxdepth 1 -type d)

count=0
for i in $FOLDERS_TO_SEARCH
do
        count=$(($count+1))
        if [[ $count -eq 1 ]];then
                echo "Skipping root directory: $i"
        else
                find $i -maxdepth 1 -type f
        fi
done