Потоки Java запускают другие потоки, каждый из которых записывает в массив

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

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

Итак, я делаю это правильно до сих пор? Как я могу сделать run() доступ к массиву результатов демонстрации и записать в него случайное число потока? Кроме того, как run() может связаться с другими потоками (из threadList), чтобы уведомить их?

Благодарю вас.

public class gijos extends Thread {

    private int length; 
    private int position;

    public gijos(int arrPos) { 
      position = arrPos;
    } 

    public int getPosition(){
       return position;
    }

    public void run() {   
             Random rand = new Random();
             int  n = rand.nextInt(51) + 1;
    }

public class demo { 

    public static void main (String[] args) { 

            System.out.println("Array length / thread count:");

            Scanner s = new Scanner(System.in);
            int N = s.nextInt();

            int[] resultArray = new int[N];

            gijos[] threadList = new gijos[N]; 

            for(int i = 0; i < N; i++){
                threadList[i] = new gijos(i);
            } 

    }

}

person GytisK    schedule 23.10.2014    source источник
comment
Мой главный комментарий будет заключаться в том, что если вы совершенно новичок в Java, то это не та проблема, с которой нужно резать зубы!   -  person chiastic-security    schedule 24.10.2014
comment
Я полностью согласен, но мне дали несколько строк кода, которые показывали, как создать поток, заставить его печатать слово, и некоторые люди считают, что этого достаточно. Если бы я мог понять, как заставить поток run() писать в массив и разбудить другие потоки, я думаю, что смогу понять остальное.   -  person GytisK    schedule 24.10.2014
comment
Метод notifyAll() уведомляет все ожидающие потоки. Я думаю, вам нужно научиться ждать (), уведомлять всех ()   -  person Gurkan İlleez    schedule 24.10.2014
comment
Как тебе это дали? Это домашнее задание? Вы должны обратиться за помощью к своему ассистенту или профессору, они должны знать, когда у студентов возникают проблемы с заданием.   -  person markspace    schedule 24.10.2014
comment
Как насчет записи значений в resultArray из каждого потока?   -  person GytisK    schedule 24.10.2014
comment
Сделать массив глобальным. Самый простой способ — определить массив как статический.   -  person Gurkan İlleez    schedule 24.10.2014
comment
Каждый поток должен передать массив результатов и индекс [next] следующему потоку, который он создает/запускает, и ожидает в массиве. Последний поток (на основе индекса ›= max) должен уведомить массив, чтобы другие потоки проснулись. Поток реализуется с конструктором (Object[], int).   -  person srkavin    schedule 24.10.2014
comment
srkavin, вам все равно нужно передать весь массив следующему потоку, если массив глобальный? Кроме того, означает ли «определение массива как статического» включение public static int[] resultArray; до демонстрации main? тогда он будет доступен с помощью run() как demo.resultArray?   -  person GytisK    schedule 24.10.2014
comment
@GytisK, если вы собираетесь использовать статический массив, вам нужно будет передать только индекс (или) использовать глобальный/статический/переходный int.   -  person srkavin    schedule 24.10.2014


Ответы (1)


Вот пример рабочего класса:

public class ArrayWorker implements Runnable {
    private static final List<ArrayWorker> threadList = new LinkedList<>();
    private static final Random rnd = new Random(System.currentTimeMillis());

    private final int[] array;
    private final int index;


    public ArrayWorker(final int[] array, final int index) {
        if (index > array.length - 1) {
            throw new IndexOutOfBoundsException(String.format("%d", index - array.length));
        }

        this.array = array;
        this.index = index;
        System.out.println(this + " has been created");
    }


    @Override
    public void run() {
        System.out.println(this + " run()");
        this.array[this.index] = rnd.nextInt(100);

        if (index < array.length - 2) {
            final ArrayWorker worker = new ArrayWorker(array, index + 1);

            System.out.println(this + " has created: " + worker);
            new Thread(worker).start();

            threadList.add(this);
            try {
                synchronized (this) {
                    System.out.println(this + " is now waiting");
                    this.wait();
                    System.out.println(this + " got notified");
                }
            } catch (InterruptedException ex) {
                System.out.println("Error while waiting for termination");
                threadList.remove(this);
            }
        } else {
            threadList.forEach(worker -> {
                synchronized(worker) {
                    System.out.println(this + " notifying: " + worker);
                    worker.notify();
                }
            });
        }
    }

    @Override
    public String toString() {
        return "WorkerThread[" + index + "]";
    }  
}

Здесь использование:

public static void main(String[] args) {
    final int[] myArray = new int[10];

    System.out.println("MainThread creating first WorkerThread and awaiting termination of last WorkerThread");
    Thread t = new Thread(new ArrayWorker(myArray, 0));
    try {
        t.start();
        t.join();
    } catch (InterruptedException ex) {
        ex.printStackTrace();
        System.exit(-1);
    }

    System.out.println("Last WorkerThread finished");
    for (int i : myArray) {
        System.out.print(i + " ");
    }
    System.out.println();
}

Пример вывода:

MainThread creating first WorkerThread and awaiting termination of last WorkerThread
WorkerThread[0] has been created
WorkerThread[0] run()
WorkerThread[1] has been created
WorkerThread[0] has created: WorkerThread[1]
WorkerThread[1] run()
WorkerThread[0] is now waiting
WorkerThread[2] has been created
WorkerThread[1] has created: WorkerThread[2]
WorkerThread[1] is now waiting
WorkerThread[2] run()
WorkerThread[3] has been created
WorkerThread[2] has created: WorkerThread[3]
WorkerThread[2] is now waiting
WorkerThread[3] run()
WorkerThread[3] notifying: WorkerThread[2]
WorkerThread[3] notifying: WorkerThread[1]
WorkerThread[2] got notified
WorkerThread[3] notifying: WorkerThread[0]
WorkerThread[1] got notified
WorkerThread[0] got notified
Last WorkerThread finished
Results:
10 25 73 7 
person ifloop    schedule 24.10.2014
comment
Благодарю вас. Именно то, что мне было нужно. У меня есть несколько вопросов, если вы не возражаете: 1. Действительно ли нужны @Override? (На самом деле это нигде не будет "использоваться", просто задача) 2. Какая разница, что "финал" имеет значение в этой программе? 3. Есть ли способ сделать так, чтобы результат печати всегда отображался в конце? Если я запущу его несколько раз, он выведет результат так быстро, что сообщения о запуске потока будут в конце: D - person GytisK; 24.10.2014
comment
@GytisK 1. Это на самом деле не нужно, просто хороший стиль кодирования помогает компилятору помочь вам предотвратить ошибки. 2. Опять же, это хорошая практика, помогающая свести к минимуму вероятность появления ошибок. 3. Да, вы должны использовать регистратор (который сохранит порядок отладочных сообщений и распечатает их в порядке очереди) - person ifloop; 27.10.2014
comment
Без threadList, как бы я уведомил все потоки с последним потоком? Я использовал (в основном) else { synchronized(this){this.notifyAll()} } и не останавливает программу после завершения. - person GytisK; 27.10.2014