![](/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.