使用多线程

发布于 2025-01-28 05:48:32 字数 396 浏览 2 评论 0原文

我是这个小组的新手,所以我相信可以在这里获得帮助,因为我在Google上找不到有关我问题的任何信息。

我正在尝试实现java factodd换位排序。因此,当我算法时,我认为分为分区是一个好主意:

  1. 如何知道我应该将数组列表划分多少部分?例如,我现在使用17个元素使其更容易理解。
  2. 另外,我不知道我是否应该使用所谓的执行人员服务或正常创建线程。

我在此处添加我当前的逻辑:从奇数阶段开始,然后分为两个部分,然后分配两个线程以进行这些比较,此后创建了等待线程的障碍,因此启动其他线程以类似地与偶数索引一起使用。感谢您可以给我的任何帮助。目前,我不知道如何实现此算法,因此任何单词都可能会有所帮助。 ://i.sstatic.net/osvjl.png“ alt =”在此处输入图像描述”>

I am new to this group, so I believe it is a possibility to get help here since I could not find any information about my question on Google.

I am trying to implement Java EvenOdd transposition sort parallel. Therefore, as I algorithm I thought that dividing into partitions would be a great idea:

  1. How to know how many parts should I divide my array list? For example, I use 17 elements for now to make it more understandable.
  2. Also, I do not know if I should use something called ExecutorService or just create threads normally.

I add my current logic here: Start from the Odd phase and divide into two parts and assign two threads to make these comparisons, after that create a Barrier to wait for threads and therefore start other threads to work with the even indexes similarly. Thanks for any help that you could give me. Currently, I do not know how to implement this algorithm, so any words might help.enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

初吻给了烟 2025-02-04 05:48:32

如何知道我应该将几个部分划分我的数组列表?例如,我现在使用17个元素使其更容易理解。

您将数组分为子阵列的直觉是正确的,因为它通常是并发排序算法的基础。如您所知,我们只需要讨论实现:

  1. 直观的解决方案就是为每个奇数索引创建thread比较swap和join()它们到主线程等待结果。 rince并重复此n次。但是,这是非常低效的,因为创建和启动所有o(n^2)线程的开销对于快速比较和换档而言,这远远大。
  2. 我们还可以为每个奇数索引创建线程,并使其在左右之间反复比较和交换。这是有问题的,因为我们必须反复左右锁定(以防止数据竞赛),这将导致调度程序的许多无用的开销,我们不知道何时完成。
  3. 最后,我们可以为每个奇数索引创建线程,还可以使它们在左右之间反复交替,并且每次都使它们在障碍物上等待。对于我来说,这似乎是正确的选择,因为它可以最大程度地减少线程管理开销,还限制了无用的比较和数据竞赛。

这使我们获得了以下代码:

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),这不是对这种并行算法的最佳选择。您可以尝试在Parrallel中实现的另一种算法是 noreflow noreferrer“ >算法。您可以与此相关的很多东西,但是最重要的是合并,因为它是顺序算法中的瓶颈。您可以查看 nofollow noreferrer“> strong>或查看其他并行合并

另外,我不知道我是否应该使用“执行人员服务”或正常创建线程。

Java为并行性提供了许多不同的工具,这些工具在不同级别的抽象级别运行。可以说 比基本线程更“高级”,因为它简化了线程管理。它还将优化任务的调度,以使执行更好。

这是我们的实现,使用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();}
        }
    }   
}

如您所见,我们使用的是线程 factory newfixedthreadpool静态方法生成和刻有所有胎面。然后,我们将任务添加到线程池中,将返回a 未来 变量。 Future将在线程完成时(在我们的情况为null)时保持值。呼叫 .get() 方法将等待结果(因此要完成的线程)。请注意,您想实现某种嵌套的线程偏中性主义(例如,在平行Mergesort时)。您应该使用 > 专门为此而制作。最后,在这里是一个关于executorService

How to know how many parts should I divide my array list? For example, I use 17 elements for now to make it more understandable.

Your intuition to divide the array into subarrays is correct, as it is often the basis for concurrent sorting algorithms. As you know the algorithm already, we only have to discuss the implementation :

  1. The intuitive solution would be to create a thread for every odd index, start() all of them for the compare-and-swap and join() them to the main thread to wait on the result. Rince and repeat this N times. This is very inefficient, however, as the overhead of creating and starting all of the O(N^2) threads is far to big for the fast compare-and-swap.
  2. We can also create threads for every odd index, and make them repeatedly compare-and-swap between left and right. This is problematic as we would have to lock left and right repeatedly (to prevent data races), would lead to a lot of useless overhead with the scheduler and we wouldn't know when we are finished.
  3. Lastly, we can create threads for every odd index, also make them repeatedly alternate between left and right and, every time, make them wait on a barrier. This seems for me to be the correct option as it minimizes thread management overhead and also limits useless comparisons and data races.

This leads us to the following code :

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();}
        }
    }   
}

Notice that this algorithm has a runtime of O(n) which is not the best for such a parallel algorithm. Another algorithm you can try to implement in parrallel is the MergeSort algorithm. There are a lot of things you can parallelize with this one, but the most important one is the merging, as it is the bottleneck in the sequential algorithm. You can look at Batcher Odd-Even Mergesort or look at other parallel merges.

Also, I do not know if I should use something called ExecutorService or just create threads normally.

Java provides a lot of different tools for parallelism, which operate at different levels of abstraction. One could say that ExecutorService is more 'high-level' than basic threads, as it simplifies the thread managment. It also will optimize scheduling of tasks, as to make execution better.

Here is our implementation, using 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();}
        }
    }   
}

As you can see, we are using the thread factory newFixedThreadPool static method to generate and intantiate all the treads. We then add our tasks to the thread pool, which will return a Future variable. A Future will hold the value, when the thread finished (in our case null). Calling the Future.get() method will wait for the result (and thus the thread to be finished). Notice that is you want to implement some sort of nested thread parralelism (for example, when parallelizing MergeSort). You should use ForkJoinPool as it is made specifically for that. Finally, here is a good tutorial about ExecutorService.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文