创建大量线程

时间:2019-05-06 22:46:52

标签: java multithreading sorting parallel-processing synchronization

我正在研究一种排序算法,以显示名为BITONIC的多线程执行,但是我发现使用multhread来运行它的方式是创建新对象并在静态数组中工作,但是这导致了我难以置信的缓慢排序,通过一些调试-阅读打印品-我发现我正在创建大量的线程,因此创建了大量对象,我想是因为它是如此缓慢,但我无法真正解决问题,所以如果您能给我一些提示,我将非常感激。

Bitonic排序类似于合并,真正了解算法不是真正必要的,只需了解线程和Java

在这里,我具有一些具有单独线程的属性

    public static int[] data;

    private int start, end, size;
    private boolean direction;

    private int minimumLength = 1;

    private final boolean Ascending = true, Descending = false;

我有2个构造函数,第一个实例,它们将从外部分配的向量中设置值

    public MultiThreadedSorter (int[] originalData)
    {
        data = originalData;

        start = 0;
        end = size = data.length;
        direction = Ascending;

//        minimumLength = data.length / Runtime.getRuntime().availableProcessors();
        minimumLength = 2;
    }

另一种用于递归除法的方法,每个线程具有新值

private MultiThreadedSorter (int lo, int hi, boolean dir)
{
    start = lo;
    end = hi;
    size = hi-lo;

    direction = dir;
}

仅用于封装目的的排序

    public void Sort() 
            throws InterruptedException
    {   
        BitonicSort(start, end, direction);
    }

此处是运行覆盖

    @Override
    public void run()
    {
        try
        {
            BitonicSort(start, end, direction);
        } catch (InterruptedException ex)
        {
            Logger.getLogger(MultiThreadedSorter.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

我认为问题出在这里

    private void BitonicSort(int _lo, int _hi, boolean dir) 
            throws InterruptedException // join()
    {   

        int length = _hi - _lo;

//        System.out.println(Thread.currentThread().getName() + " - CRIADA");
//        System.out.printf("%d\t%d\n", _lo, _hi);

        if (length > 1)
        {
//            Show ("SORT", true);

            if (length > minimumLength)
            {
                int mid = length / 2;

                System.out.println("-- left - " + Thread.currentThread().getName());
                MultiThreadedSorter leftSorterObj = new MultiThreadedSorter(_lo, _lo+mid, Ascending);
                Thread left = new Thread(leftSorterObj);

                left.start(); // i think that the problem is here
                left.join(); // or here

                System.out.println("-- rigth - " + Thread.currentThread().getName());
//                System.out.printf("%d\t%d\n", _lo+mid, _hi);
                MultiThreadedSorter rightSorterObj = new MultiThreadedSorter(_lo+mid, _hi, Descending);
                Thread right = new Thread(rightSorterObj);

                right.start(); // i think that the problem is here
                right.join(); // or here

//                System.out.println(Thread.currentThread().getName() + " - ENDED\n");
            }
            else
            {
                int mid = (length / 2);

                if (mid > 1)
                {
//                    Show ("R1", false);
                    BitonicSort(_lo, mid, Ascending);
//                    Show ("R2", false);
                    BitonicSort(_lo+mid, mid, Ascending);
                }
            }

            BitonicMerge(_lo, _hi, dir);
        }
    }

现在,我将发布主类和完整类,仅当您要执行时

主要:

    public class Program
    {
        public static void main(String[] args) throws InterruptedException
        {
            Random random = new Random();

            int arraySize = (int) Math.pow(2, 7);
            int[] originalData = new int[arraySize];

            int lim = 20;

            for (int i = 0; i < originalData.length; i++)
                originalData[i] = random.nextInt(lim);

            System.out.println(Arrays.toString(originalData));
            System.out.printf("\n");

            MultiThreadedSorter mult = new MultiThreadedSorter(originalData);
            mult.Sort();

            System.out.println(Arrays.toString(originalData));
            System.out.println();
    }

MultiThreadedSorter类别

    public class MultiThreadedSorter //extends BaseBitonicSorter
            implements Runnable
    {
        public static int[] data;

        private int start, end, size;
        private boolean direction;

        private int minimumLength = 1;

        private final boolean Ascending = true, Descending = false;

        public MultiThreadedSorter (int[] originalData)
        {
            data = originalData;

            start = 0;
            end = size = data.length;
            direction = Ascending;

    //        minimumLength = data.length / Runtime.getRuntime().availableProcessors();
            minimumLength = 2;
        }

        // Construtor chamados por cada thread antes de iniciar
        private MultiThreadedSorter (int lo, int hi, boolean dir)
        {
            start = lo;
            end = hi;
            size = hi-lo;

            direction = dir;
        }

        public void Show (String msg, boolean r)
        {
            System.out.println(Thread.currentThread().getName() + "\t" + msg);

            if (r)
                System.out.printf("De: %d\tAte: %d\t Dir: %d\n", start, end, direction ? 1 : 0);
        }

        @Override
        public void run()
        {
            try
            {
                BitonicSort(start, end, direction);
            } catch (InterruptedException ex)
            {
                Logger.getLogger(MultiThreadedSorter.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        public void Sort() 
                throws InterruptedException
        {   
            BitonicSort(start, end, direction);
        }

        private void BitonicSort(int _lo, int _hi, boolean dir) 
                throws InterruptedException // join()
        {   

            int length = _hi - _lo;

    //        System.out.println(Thread.currentThread().getName() + " - CRIADA");
    //        System.out.printf("%d\t%d\n", _lo, _hi);

            if (length > 1)
            {
    //            Show ("SORT", true);

                if (length > minimumLength)
                {
                    int mid = length / 2;

                    System.out.println("-- left - " + Thread.currentThread().getName());
                    MultiThreadedSorter leftSorterObj = new MultiThreadedSorter(_lo, _lo+mid, Ascending);
                    Thread left = new Thread(leftSorterObj);

                    left.start();
                    left.join();

                    System.out.println("-- rigth - " + Thread.currentThread().getName());
    //                System.out.printf("%d\t%d\n", _lo+mid, _hi);
                    MultiThreadedSorter rightSorterObj = new MultiThreadedSorter(_lo+mid, _hi, Descending);
                    Thread right = new Thread(rightSorterObj);

                    right.start();
                    right.join();

    //                System.out.println(Thread.currentThread().getName() + " - ENDED\n");
                }
                else
                {
                    int mid = (length / 2);

                    if (mid > 1)
                    {
    //                    Show ("R1", false);
                        BitonicSort(_lo, mid, Ascending);
    //                    Show ("R2", false);
                        BitonicSort(_lo+mid, mid, Ascending);
                    }
                }

                BitonicMerge(_lo, _hi, dir);
            }
        }

        private void BitonicMerge(int _lo, int _hi, boolean dir) 
                throws InterruptedException // join()
        {
    //        Show ("MERGE", true);

            int length = _hi - _lo;

            if (length > 1)
            {
                if (length > minimumLength)
                {
                    int mid = (length / 2);

                    for (int i = _lo; i < (_lo + mid); i++)
                        Compare(i, (i + mid), dir);

                    MultiThreadedSorter leftMergerObj = new MultiThreadedSorter(_lo, _lo+mid, dir);
                    Thread left = new Thread(leftMergerObj);

                    left.start();
                    left.join();

                    MultiThreadedSorter rightMergerObj = new MultiThreadedSorter(_lo + mid, _hi, dir);
                    Thread right = new Thread(rightMergerObj);

                    right.start();
                    right.join();
                }
                else
                {
                    int mid = (length / 2);

                    for (int i = _lo; i < (_lo + mid); i++)
                        Compare(i, (i + mid), dir);

                    if (mid > 1)
                    {
                        BitonicMerge(_lo, _lo + mid, dir);
                        BitonicMerge(_lo + mid, _hi, dir);
                    }
                }
            }
        }

        private synchronized void Compare(int src, int dst, boolean dir)
        {
            if (dir == (data[src] > data[dst]))
                Exchange(src, dst);
        }

        protected synchronized void Exchange(int i, int j)
        {
            int temp = data[i];
            data[i] = data[j];
            data[j] = temp;
        }
    }

1 个答案:

答案 0 :(得分:0)

为什么这么慢:

问题:您对进程可以创建的线程数不加任何限制,并且您正在递归地创建可能导致饱和的线程。

解决方案::使用线程池限制创建的线程数量(每个系统可以创建的线程数量有限)并减少线程的启动时间(每次使用new时) Thread(Runnable).start()用于创建新线程)。线程池可以通过Executors接口进行管理。

问题:在并发方面,您的Compare和Exchange方法阻止所有线程的执行,因为它们被描述为synchronized,因此只能由一个线程在以下位置运行一个时间。

解决方案::制作数据volatile