2015-10-26 5 views
2

Я чувствую себя виноватым, обращаясь к StackOverflow за помощью в школе, но я исчерпал свои ресурсы и не могу понять это для жизни меня. Для одного из моих классов мне необходимо понять, как построить и правильно использовать Семафоры в Java. Одно из упражнений имеют следующий код:Использование семафоров в Java

import java.lang.Thread; 
import java.util.concurrent.*; 

public class ThreadSync 
{ 
    private static boolean runFlag = true; 

    public static void main(String[] args) { 
     Runnable[] tasks = new Runnable[37]; 
     Thread[] threads = new Thread[37]; 
     // create 10 digit threads 
     for (int d=0; d<10; d++) { 
      tasks[d] = new PrintDigit(d); 
      threads[d] = new Thread(tasks[d]); 
      threads[d].start(); 
     } 
     // create 26 letter threads 
     for (int d=0; d<26; d++) { 
      tasks[d+10] = new PrintLetter((char)('A'+d)); 
      threads[d+10] = new Thread(tasks[d+10]); 
      threads[d+10].start(); 
     } 
     // create a coordinator thread 
     tasks[36] = new PrintSlashes(); 
     threads[36] = new Thread(tasks[36]); 
     threads[36].start(); 

     // Let the threads to run for a period of time 
     try { 
      Thread.sleep(50); 
     } 
     catch (InterruptedException ex) { 
      ex.printStackTrace(); 
     } 
     runFlag = false; 

     // Interrupt the threads 
     for (int i=0; i<37; i++) threads[i].interrupt(); 
    } 

    public static class PrintDigit implements Runnable 
    { 
     int digit; 
     public PrintDigit(int d) { digit=d; } 
     public void run(){ 
      while (runFlag) { 
       System.out.printf("%d\n", digit); 
      } 
     } 
    } 
    public static class PrintLetter implements Runnable 
    { 
     char letter; 
     public PrintLetter(char c) { letter=c; } 
     public void run(){ 
      while (runFlag) { 
       System.out.printf("%c\n", letter); 
      } 
     } 
    } 
    public static class PrintSlashes implements Runnable 
    { 
     public void run(){ 
      while (runFlag) { 
       System.out.printf("%c\n", '/'); 
       System.out.printf("%c\n", '\\'); 
      } 
     } 
    } 
} 

Мне нужно изменить код, только путем добавления «семафор связанного заявления», так что программа неоднократно печатает «/», а затем три цифры, то '\', за которым следуют две буквы.

пример они дают следующим образом:

/156\BA/376\YZ/654\JK/257\HG/445\DD… 

Любая помощь будет принята с благодарностью. Я, как правило, очень хорошо учился сам, но у этих нитей голова крутится! Благодаря!

+0

Итак, вы говорите, что заявления «семафора» - это, по сути, заявления ожиданного ожидания? – ChiefTwoPencils

ответ

3

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

Пример несколько неточно, потому что нити не используются для их обычной цели, что позволяет выполнять параллельное выполнение, а скорее как упражнение для понимания семафоров. В результате семафоры также должны использоваться несколько нестандартным образом, как сигналы между потоками, а не для их нормального использования ресурсов управления. Вы поймете, как семафоры работают в этом надуманном деле, но не могут понять, как они используются в нормальном случае. Однако это можно зафиксировать, прочитав Javadoc в классе Semaphore, так что вернемся к надуманному делу вашего инструктора.

Довольно ясно, что поток, выполняемый PrintSlashes.run(), предназначен для управления диспетчером, определения, когда выполняются потоки цифр и когда запускаются потоки символов. Он должен указывать потоки цифр, когда они могут запускаться, и он должен указывать потоки символов, когда они могут запускаться. Кроме того, он должен знать, когда были напечатаны три цифры, и ему нужно знать, когда были напечатаны два символа. Это четыре части информации, которые нужно перенести, для которых самой простой моделью является использование четырех объектов Семафор.

Объекты семафоров должны представлять следующие четыре вещей:

  • Цифр доступны для печати
  • Цифры, которые были напечатаны (после последней косой черты)
  • символов доступны для печати
  • Персонажи, которые были напечатаны (после последней обратной косой черты)

PrintDigit.run() должен получить разрешение на использование семафора с цифрами перед печатью каждой цифры; который позволяет вводить цифры семафора для ограничения печати цифр до трех одновременно. После печати цифры метод должен освободить разрешение от цифр, напечатанного семафором, - обратите внимание, а не на число доступных семафоров - чтобы указать, что цифра была напечатана. Я уверен, что вы можете понять, что должен сделать PrintLetter.run(). Кстати, тот факт, что нить приобретает один семафор, но выпускает другой семафор, является одним из способов, которым этот пример надуман; обычно потоки выпускают те же семафоры, которые они приобретают.

PrintSlashes.run() должен выпустить три разрешения из числа доступных семафоров после печати косой черты, а затем получить три разрешения от цифр, напечатанных семафором, перед печатью обратной косой черты. Освобождение трех цифр позволяет потокам PrintDigit печатать три цифры, и ожидание получения трехзначных цифр обеспечивает печать трех цифр перед продолжением. Опять же, вы должны иметь возможность выяснить, что произойдет после печати обратной косой черты.

Обратите внимание, что цифры семафорных объектов должны быть инициализированы с помощью 0 разрешений, так что потоки цифр будут ждать, пока поток слэшей не выключится.

Два дополнительных предостережений:

  1. сделать код работу в качестве выходных шоу образца, вам также необходимо удалить \n из каждой печатной строки, или каждый символ будет на другой линии. Тем не менее, инструктор может захотеть, чтобы каждый символ находился в другой строке, и дал вам плохой результат выборки. Вам нужно угадать, чего он действительно хочет.

  2. Если вы хотите сделать свой код пуленепробиваемым, возможно, потребуется синхронизировать System.out, как описано в:

    Synchronization and System.out.println

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

Наконец, следующие поправки должны быть сделаны, чтобы исправить дополнительные плохие методы в коде:

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

  • Значимые константы, такие как «10», «26», «36» и «37» в этом коде, не должны быть записаны как литералы, а вместо этого должны использовать определенные константы, например static final int NUMBER_OF_DIGITS = 10;. Тогда сам код может использовать символ NUMBER_OF_DIGITS, что делает его более разборчивым, а также более удобным для обслуживания, поскольку вы можете легко изменить значение константы - например, до 8, если вы хотите преобразовать код в восьмеричный - без беспокойства, Пропустите некоторые вхождения константы.

  • Значимые константы особенно не должны быть написаны как литералы, если у них есть логические отношения. В этом случае даже static final int NUMBER_OF_CHARACTERS = 36 не является хорошей практикой; он должен быть static final int NUMBER_OF_CHARACTERS = NUMBER_OF_DIGITS + NUMBER_OF_LETTERS;, делая логические и числовые отношения четкими.

ли вы на самом деле хотите, чтобы сделать эти исправления в работе вы включаете в зависимости от того, что вы думаете, реакция инструктора будет время дают хорошие корректировки.

+0

Ваш комментарий определенно помог мне заполнить это. Дело только в том, что символыPrintedSemaphore должны быть инициализированы значением 2, чтобы его можно было получить с помощью PrintSlashes перед запуском программы для достижения цикла. Если я что-то не упустил! В любом случае, спасибо! –

+0

Хорошая точка. Я обновлю ответ. Правка: true, если вы положили приобретать символыPrintedSemaphore в начале цикла while.Если он находится в конце цикла while, он должен быть инициализирован равным 0. В любом случае это работает. –

Смежные вопросы