Java中计算最小值和最大值的多线程
我已经编写了使用多线程计算给定数组中的最小数和最大数的代码。这个想法类似于Java中计算最小值和最大值的多线程,java,multithreading,recursion,Java,Multithreading,Recursion,我已经编写了使用多线程计算给定数组中的最小数和最大数的代码。这个想法类似于binarysearch,我只是将数组分成两半,计算每一半的最小值和最大值,并相应地更新我的最小值和最大值字段。 这可能是一个用于多线程的愚蠢示例。但既然我考虑过这个问题,我就想实现它,看看它是如何运行的。到目前为止,代码的工作方式令人惊讶地正确。我希望它不会给出正确的结果,因为我不会等待第一个线程完成,我会立即启动第二个线程。这意味着最小值和最大值不能正确更新。 有人能指出为什么这在多次运行和任何改进空间中都能正常工作吗
binarysearch
,我只是将数组分成两半,计算每一半的最小值和最大值,并相应地更新我的最小值和最大值字段。
这可能是一个用于多线程的愚蠢示例。但既然我考虑过这个问题,我就想实现它,看看它是如何运行的。到目前为止,代码的工作方式令人惊讶地正确。我希望它不会给出正确的结果,因为我不会等待第一个线程完成,我会立即启动第二个线程。这意味着最小值和最大值不能正确更新。
有人能指出为什么这在多次运行和任何改进空间中都能正常工作吗
代码在这里
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);
}
}
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入java.util.Set;
公共类MinMax实现了Runnable{
Long min=Long.MAX_值;
长最大值=长最小值;
int低;
int高;
长[]arr;
公共最小最大值(整数低、整数高、长[]arr){
这个.低=低;
这个。高=高;
this.arr=arr;
}
@凌驾
公开募捐{
System.out.println(“称为run”);
如果(低-高-最大)集合。最大(l):最大;
}
否则{
System.out.println(Thread.currentThread());
int mid=(高+低)/2;
左最小最大值=新的最小最大值(低、中、arr);
右最小最大值=新的最小最大值(中、高、arr);
螺纹t1=新螺纹(左);
螺纹t2=新螺纹(右侧);
t1.start();
t2.start();
Set threadset=Thread.getAllStackTraces().keySet();
用于(螺纹t:螺纹组)
System.out.println(t.getName());
试一试{
t1.join();
t2.连接();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
公共静态void main(字符串[]args){
长[]arr={3,4,51123567,78,90,535434,1,34,56111,2,5678987645343535};
Long[]newarr=新长[arr.length];
int i=0;
用于(长期温度:arr)
newarr[i++]=temp;
最小最大值m=新的最小最大值(0,arr.length,newarr);
m、 run();
系统输出打印项次(m.min);
系统输出打印项次(m.max);
}
}
我对您的代码的评论-首先,需要声明min
和max
以确保它们的值在线程内及时更新
然后,此比较不是原子的,您可能需要将其包装到synchronized
块中,或者如果synchronized
性能不令人满意,则考虑AtomicInteger
的compareAndSet
优化:
min=Collections.min(l) < min ? Collections.min(l) : min;
max=Collections.max(l) > max ? Collections.max(l) : max;
min=Collections.min(l)最大值?集合。最大值(l):最大值;
所以问题可能是两个线程同时计算它们的最小值,但是它们在不同的时间分配它,所以赢家是谁的结果先被写入
正如@JamesKingsbery所注意到的,您可能需要在第二个线程上调用start()
这可能是最后一件事,在您的情况下,您可能不会得到任何性能提升,但这是一个值得研究的好例子。我对您的代码的评论-首先,
min
和max
需要声明为volatile
,以确保它们的值在线程内及时更新
然后,此比较不是原子的,您可能需要将其包装到synchronized
块中,或者如果synchronized
性能不令人满意,则考虑AtomicInteger
的compareAndSet
优化:
min=Collections.min(l) < min ? Collections.min(l) : min;
max=Collections.max(l) > max ? Collections.max(l) : max;
min=Collections.min(l)最大值?集合。最大值(l):最大值;
所以问题可能是两个线程同时计算它们的最小值,但是它们在不同的时间分配它,所以赢家是谁的结果先被写入
正如@JamesKingsbery所注意到的,您可能需要在第二个线程上调用start()
这可能是最后一件事,在你的情况下,你可能不会得到任何性能提升,但这是一个很好的例子来研究。为什么它有效?第一次
low
是0
,high
是18
low-high为什么有效?第一次low
是0
和>high
大约是18
low-high为此使用递归动作
类。这里我使用递归动作
编写了程序。请查找下面的代码。有关更多信息,请查看
package org.kavi.threadexample;
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入java.util.concurrent.ForkJoinPool;
导入java.util.concurrent.RecursiveAction;
公共类MinMax扩展了递归操作{
Long min=Long.MAX_值;
长最大值=长最小值;
int低;
int高;
长[]arr;
公共最小最大值(整数低、整数高、长[]arr){
这个.低=低;
这个。高=高;
this.arr=arr;
}
@凌驾
受保护的void compute(){
如果(低-高-最大)集合。最大(l):最大;
}
否则{
int mid=(低+高)>>>1;
左最小最大值=新的最小最大值(低、中、arr);
右最小最大值=新的最小最大值(中、高、arr);
}
}
公共静态void main(字符串[]args){
长[]arr={3,4,51123567,78,90,535434,1,34,56111,2,5678987645343535};
Long[]newarr=新长[arr.length];
int i=0;
用于(长期温度:arr){
newarr[i++]=temp;
}
最小最大值m=新的最小最大值(0,arr.length,newarr);
ForkJoinPool池=新的ForkJoinPool();
调用池(m);
系统
package org.kavi.threadexample;
import java.util.Arrays;
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 (high - low <= 2) {
System.out.println(Arrays.toString(Arrays.copyOfRange(arr, low, high)));
if (low == high) {
min = max = arr[low];
} else {
min = Math.min(arr[low], arr[low + 1]);
max = Math.max(arr[low], arr[low + 1]);
}
} else {
// make the left side an exact power of two
int leftWidth = 1 << (30 - Integer.numberOfLeadingZeros(high - low));
MinMax left = new MinMax(low, low + leftWidth, arr);
MinMax right = new MinMax(low + leftWidth, high, arr);
invokeAll(left, right);
min = Math.min(left.min, right.min);
max = Math.max(left.max, right.max);
}
}
public static void main(String[] args) {
Long[] arr = {3L, 4L, 5L, 1123L, 567L, 78L, 90L, 5L, 35434L, 1L, 34L, 56L, 111L, 2L, 56L, 789L, 87645L, 343535L};
MinMax m = new MinMax(0, arr.length, arr);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(m);
System.out.println(m.min);
System.out.println(m.max);
}
}