![](/img/trans.png)
[英]How to write a code that prints odd-even numbers using for-each loop on an array in java
[英]Odd-Even sort Java using multithreading
我是这个小组的新手,所以我相信有可能在这里获得帮助,因为我在 Google 上找不到关于我的问题的任何信息。
我正在尝试并行实现 Java EvenOdd 转置排序。 因此,在我的算法中,我认为划分为分区将是一个好主意:
我在这里添加我当前的逻辑:从奇数阶段开始,分成两部分并分配两个线程进行这些比较,然后创建一个屏障来等待线程,因此启动其他线程以类似地使用偶数索引。 感谢您能给我的任何帮助。 目前,我不知道如何实现这个算法,所以任何话都可能会有所帮助。
欢迎来到 StackOverflow!
如何知道我应该划分我的数组列表多少部分? 例如,我现在使用 17 个元素以使其更易于理解。
您将数组划分为子数组的直觉是正确的,因为它通常是并发排序算法的基础。 正如你已经知道的算法,我们只需要讨论实现:
thread
, start()
所有这些索引用于比较和交换,并将它们join()
到主线程以等待结果。 冲洗并重复此N
次。 然而,这是非常低效的,因为创建和启动所有O(N^2)
线程的开销对于快速比较和交换来说非常大。这导致我们得到以下代码:
import java.util.Arrays;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class OddEvenSort {
public static void main(String[] args) {
int[] arr = {83, 71, 72, 26, 6, 81, 53, 72, 20, 35, 40, 79, 3, 90, 89, 52, 30};
sortArr(arr);
System.out.println(Arrays.toString(arr));
}
public static void sortArr(int[] arr) {
int threadNum = arr.length/2;
CyclicBarrier barr = new CyclicBarrier(threadNum);
Thread[] threads = new Thread[threadNum];
for (int i = 0; i < threadNum; i++) {
threads[i] = new Thread(new CompareSwapThread(arr, 2*i + 1, barr));
threads[i].start();
}
for (int i = 0; i < threadNum; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {e.printStackTrace();}
}
}
}
class CompareSwapThread implements Runnable {
private int[] arr;
private int index;
private CyclicBarrier barr;
public CompareSwapThread(int[] arr, int index, CyclicBarrier barr) {
this.arr = arr;
this.index = index;
this.barr = barr;
}
@Override
public void run() {
for (int i = 0; i < arr.length; i++) {
if (arr[index - 1] > arr[index]) {
int t = arr[index - 1];
arr[index - 1] = arr[index];
arr[index] = t;
}
try {
barr.await();
} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}
if (index + 1 < arr.length && arr[index] > arr[index + 1]) {
int t = arr[index];
arr[index] = arr[index + 1];
arr[index + 1] = t;
}
try {
barr.await();
} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}
}
}
}
请注意,该算法的运行时间为O(n)
,这对于这种并行算法来说并不是最好的。 您可以尝试并行实现的另一种算法是MergeSort算法。 有很多事情可以用这个并行化,但最重要的是合并,因为它是顺序算法的瓶颈。 您可以查看Batcher Odd-Even Mergesort或查看其他并行合并。
另外,我不知道我是否应该使用名为 ExecutorService 的东西或只是正常创建线程。
Java 提供了许多不同的并行工具,它们在不同的抽象级别上运行。 可以说ExecutorService
比基本线程更“高级”,因为它简化了线程管理。 它还将优化任务的调度,以使执行更好。
这是我们的实现,使用ExecutorService
:
import java.util.Arrays;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class OddEvenSort {
public static void main(String[] args) {
int[] arr = {83, 71, 72, 26, 6, 81, 53, 72, 20, 35, 40, 79, 3, 90, 89, 52, 30};
sortArr(arr);
System.out.println(Arrays.toString(arr));
}
public static void sortArr(int[] arr) {
int threadNum = arr.length/2;
CyclicBarrier barr = new CyclicBarrier(threadNum);
ExecutorService exec = Executors.newFixedThreadPool(threadNum);
Future<?>[] awaits = new Future<?>[threadNum];
for (int i = 0; i < threadNum; i++) {
awaits[i] = exec.submit(new CompareSwapThread(arr, 2*i + 1, barr));
}
for (int i = 0; i < threadNum; i++) {
try {
awaits[i].get();
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}
}
}
}
class CompareSwapThread implements Runnable {
private int[] arr;
private int index;
private CyclicBarrier barr;
public CompareSwapThread(int[] arr, int index, CyclicBarrier barr) {
this.arr = arr;
this.index = index;
this.barr = barr;
}
@Override
public void run() {
for (int i = 0; i < arr.length; i++) {
if (arr[index - 1] > arr[index]) {
int t = arr[index - 1];
arr[index - 1] = arr[index];
arr[index] = t;
}
try {
barr.await();
} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}
if (index + 1 < arr.length && arr[index] > arr[index + 1]) {
int t = arr[index];
arr[index] = arr[index + 1];
arr[index + 1] = t;
}
try {
barr.await();
} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}
}
}
}
如您所见,我们使用线程工厂newFixedThreadPool
静态方法来生成和实例化所有线程。 然后我们将任务添加到线程池中,线程池将返回一个Future
变量。 当线程完成时(在我们的例子中为 null), Future
将保存该值。 调用Future.get()
方法将等待结果(因此线程完成)。 请注意,您想要实现某种嵌套线程并行(例如,在并行化 MergeSort 时)。 您应该使用ForkJoinPool
,因为它是专门为此而设计的。 最后,这是一个关于ExecutorService
的好教程。
如果您需要任何详细信息,请随时在评论中询问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.