创建一个从其他线程接收值的线程

时间:2010-05-10 19:09:25

标签: java multithreading

Java中的这个程序创建了一个包含15个数字的列表,并创建了3个线程来搜索给定时间间隔内的最大值。我想创建另一个线程,获取这3个数字并获得最大值。但我不知道如何在另一个线程中获取这些值。

public class apple implements Runnable{

String name;
int time, number, first, last, maximum;
int[] array = {12, 32, 54 ,64, 656, 756, 765 ,43, 34, 54,5 ,45 ,6 , 5, 65};


public apple(String s, int f, int l){
    name = s;
    first = f;
    last = l;
    maximum = array[0];
}



public void run(){
    try{

        for(int i = first; i < last; i++ )
        {

            if(maximum < array[i])
            {
                maximum = array[i];
            }
        }

        System.out.println("Thread"+ name + "maximum = " + maximum);

    }catch(Exception e){}
    }



public static void main(String[] args){
    Thread t1 = new Thread(new apple("1 ", 0, 5));
    Thread t2 = new Thread(new apple("2 ", 5, 10 ));
    Thread t3 = new Thread(new apple("3 ", 10, 15));

    try{

        t1.start();
        t2.start();
        t3.start();
        }catch(Exception e){}

}

}

3 个答案:

答案 0 :(得分:2)

以下是ExecutorService和ExecutorCompletionService如何解决它:

public class MaxFinder {
    private int[] values;
    private int threadsCount;

    public MaxFinder(int[] values, int threadsCount) {
        this.values = values;   
        this.threadsCount = threadsCount;
    }

    public int find() throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(threadsCount);
        ExecutorCompletionService<Integer> cs = new ExecutorCompletionService<Integer>(executor);

        // Split the work
        int perThread = values.length / threadsCount;       
        int from = 0;
        for(int i = 0; i < threadsCount - 1; i++) {
            cs.submit(new Worker(from, from + perThread));
            from += perThread;
        }
        cs.submit(new Worker(from,values.length));

        // Start collecting results as they arrive
        int globalMax = values[0];
        try {           
            for(int i = 0; i < threadsCount; i++){
                int v = cs.take().get();
                if (v > globalMax)
                    globalMax = v;
            }
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }

        executor.shutdown();
        return globalMax;
    }

    private class Worker implements Callable<Integer> {
        private int fromIndex;
        private int toIndex;

        public Worker(int fromIndex, int toIndex) {
            this.fromIndex = fromIndex;
            this.toIndex = toIndex;
        }

        @Override
        public Integer call() {
            int max = values[0];
            for(int i = fromIndex; i<toIndex; i++){
                if (values[i] > max)
                    max = values[i];
            }
            return max;
        }       
    }
}

在此解决方案中,N个线程同时工作,每个线程在数组的部分上。调用者线程负责在到达时收集本地最大值,并找到全局最大值。此解决方案使用java.util.concurrent包中的一些非平凡的并发工具。

如果您更喜欢仅使用原始同步工具的解决方案,那么您应该在工作线程中使用synchronized块,该块设置某些数据成员中的最大值,然后通知收集器线程。收集器线程应处于循环中,等待通知,然后检查新数字,并在需要时更新全局最大值。这种“消费者生产者”模式需要仔细同步。

答案 1 :(得分:1)

根据您拥有的代码,最简单的解决方案是将主线程连接到每个实例线程,然后从中获取最大值以进行比较。像这样:

int globalMax;

try{

    t1.start();
    t2.start();
    t3.start();

    t1.join();
    globalMax = t1.maximum;

    t2.join();
    if (t2.maximum > globalMax) {
        globalMax = t2.maximum;
    }

    t3.join();
    if (t3.maximum > globalMax) {
        globalMax = t3.maximum;
    }
} catch(Exception e){
}

答案 2 :(得分:0)

尝试实现Callable,而不是实现Runnable,它能够返回结果。给出here的教程是描述如何执行此操作的良好来源。

解决问题的另一种方法可能是创建一个对象,每个apple实例(不知道你为什么称它为此)可以在对象中注册其最大值。这个新类可以传递到每个apple构造函数中,然后apple可以调用一个方法,将自己的最大值传递给它。

例如:

public class MaximumOfMaximumsFinder implements Runnable {
    private List<Integer> maximums = new ArrayList<Integer>();

    public void registerSingleMaximum(Integer max) {
        maximums.add(max);
    }

    public void run() {
         // use similar logic to find the maximum
    }
}

关于确保与其他线程协调有几个问题,我会留给你,因为有一些有趣的事情要考虑。