Java, массив, потоки, мин, не более - PullRequest
0 голосов
/ 24 апреля 2020

Я пытался написать программу, чтобы найти максимальное и минимальное значение в массиве. Я сделал первую часть. Программа делит массив на две части, показывает мин и макс от каждой половины, а затем мин и макс от целого. У меня проблема со второй частью - я не знаю, как изменить эту программу, чтобы вы могли задать любое количество потоков.

Пожалуйста, смотрите мой код:

{
    smallThread first;
    smallThread second;

    public Main(String fName, String sName)
    {
        first = new smallThread(fName);
        second = new smallThread(sName);
    }

    public static void main(String[] args)
    {
        Main main = new Main("First", "Second");
        main.startThread();
        main.waitForIt();
        main.showItBaby();
    }

    private void startThread() {
        first.start();
        second.start();
    }

    private void waitForIt() {
        while (first.isAlive() || second.isAlive()) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void showItBaby() {
        int max = smallThread.send(0);
        int min = smallThread.send(0);
        for (int i = 0; i < 20; ++i) {
            int element = smallThread.send(i);
            if (element > max) { max = element; }
            if (element < min) { min = element; }
            //System.out.println(element);
        }
        System.out.println("Min: " + min);
        System.out.println("Max: " + max);
    }
}









import java.util.Random;

public class smallThread extends Thread
{
    private int[] tab = new int[200];
    private static int[] tabX = new int[200];
    private int xNumber;
    private int yNumber;
    private int maxi;
    private int mini;
    private int aNumer = 0;

    public smallThread(String str) { super(str); }

    public synchronized void run() {

        long millisActualTime = System.currentTimeMillis();
        Random x = new Random();
        for (int i = 0; i < 20; i++) { tab[i] = x.nextInt(100); }

        if (getName().equals("First")) {
            xNumber = 0;
            yNumber = 10;
            mini = tab[0];
            maxi = tab[0];
            for (int i = xNumber; i < yNumber; i++)
            {
                if (tab[i] > maxi) { maxi = tab[i]; }
                if (tab[i] < mini) { mini = tab[i]; }
            }
            System.out.println("Min 1 thread: "+mini);
            System.out.println("Max 1 thread: "+maxi);
            adding();
        }
        if (getName().equals("Second")) {
            xNumber = 10;
            yNumber = 20;
            mini = tab[10];
            maxi = tab[10];
            for (int i = xNumber; i < yNumber; i++)
            {
                if (tab[i] > maxi) { maxi = tab[i]; }
                if (tab[i] < mini) { mini = tab[i]; }
            }
            System.out.println("Min 2 thread: "+mini);
            System.out.println("Max 2 thread: "+maxi);

            long executionTime = System.currentTimeMillis() - millisActualTime;
            System.out.println("Czas wykonania: "+executionTime);

            adding();
        }
    }

    private void adding() {
        for (int i = xNumber; i < yNumber; ++i) {
            tabX[i] = tab[i];
        }
    }

    public static int send(int a)
    {
        return tabX[a];
    }

}

1 Ответ

0 голосов
/ 25 апреля 2020

Я не уверен, каково именно ваше ожидаемое поведение, потому что я не смог получить правильный пример из вашего кода, чтобы выяснить, что он делает, и угадать, что он должен делать.

Однако: если Если вы хотите запускать дочерние задачи параллельно, вам может помочь следующий фрагмент:

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreaderApplication {
    private static final int THREADS_COUNT = 3;

    private static final int DELAY_OF_FIRST_TASK_FROM_START  = 3;
    private static final int DELAY_OF_SECOND_TASK_FROM_START = 5;
    private static final int DELAY_OF_THIRD_TASK_FROM_START  = 7;
    private static final int DELAY_OF_FOURTH_TASK_FROM_START = 9;
    private static final int DELAY_OF_FIFTH_TASK_FROM_START  = 11;
    private static final int DELAY_OF_SIXTH_TASK_FROM_START  = 14;

    public static void main(final String[] args) {
        final ScheduledExecutorService executor = Executors.newScheduledThreadPool(THREADS_COUNT);
        final Runnable task0 = new RunnableTask("Demo Task 1");
        final Runnable task1 = new RunnableTask("Demo Task 2");
        final Runnable task2 = new RunnableTask("Demo Task 3");
        final Runnable task3 = new RunnableTask("Demo Task 4");
        final Runnable task4 = new RunnableTask("Demo Task 5");
        final Runnable task5 = new RunnableTask("Demo Task 6");

        System.out.println("Planning tasks; time: " + new Date());

        executor.schedule(task0, DELAY_OF_FIRST_TASK_FROM_START, TimeUnit.SECONDS);
        executor.schedule(task1, DELAY_OF_SECOND_TASK_FROM_START, TimeUnit.SECONDS);
        executor.schedule(task2, DELAY_OF_THIRD_TASK_FROM_START, TimeUnit.SECONDS);
        executor.schedule(task3, DELAY_OF_FOURTH_TASK_FROM_START, TimeUnit.SECONDS);
        executor.schedule(task4, DELAY_OF_FIFTH_TASK_FROM_START, TimeUnit.SECONDS);
        executor.schedule(task5, DELAY_OF_SIXTH_TASK_FROM_START, TimeUnit.SECONDS);

        System.out.println("Awaiting tasks; time: " + new Date());

        executor.shutdown();
        // use executor.awaitTermination(amountOfSeconds, TimeUnit.SECONDS) if you want to wait a definite amount of time instead of shutting down upon last daemon-thread completes

        System.out.println("Main program ready to exit; time: " + new Date());
    }

    private static class RunnableTask implements Runnable {
        private final String text;

        public RunnableTask(final String text) {
            this.text = text;
        }

        @Override
        public void run() {
            System.out.println(text);
        }
    }
}

Примечания В этом состоянии основная программа выполняется почти сразу. executor.shutdown() заставляет пул больше не принимать новые Callables, но не немедленно отключает все. Вместо этого он ожидает окончания последнего потока демона.

В качестве альтернативы вы можете подождать некоторое время, используя executor.awaitTermination(amountOfSeconds, TimeUnit.SECONDS). В этом случае основной поток будет ожидать завершения в течение заданного промежутка времени, прежде чем приступить к его завершению.

В этом примере, если вы используете, например, int amountOfSeconds = 5, ваш основной поток будет ждать на executor.awaitTermination(amountOfSeconds, TimeUnit.SECONDS) в течение 5 секунд до окончания его исполнения. Тем не менее: даже если основной поток уже завершил выполнение, daemon- / child-threads этого не сделали. Поэтому перед завершением работы основного приложения выполняемые задачи RunnableTask завершаются.

Редактировать Этот код протестирован, но в нем есть много возможностей для улучшения ради гибкости. Судя по приведенному выше коду, вы должны больше разделять классы и методы (например, по интересам), и в моем примере можно утверждать, что, например, использование правильного регистратора (такого как Log4J2 или Slf4J) было бы хорошей идеей. Я упустил многое, чтобы дать гораздо более лаконичное решение.

Я также предлагаю не изобретать велосипед, если только по какой-то причине это не нужно делать. Используйте существующие подходы к созданию пула потоков (на самом деле их несколько, я только что показал один из них).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...