Установка флага остановки в потоке в значение true, нить равна нулю? - PullRequest
0 голосов
/ 30 апреля 2018

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

У меня есть три потока, один поток - слушатель, который прослушивает веб-сокет для уведомлений о том, есть ли новое расписание, которое мы должны загрузить. Этот поток запускает другой поток, который является «Schedule Downloader», он делает http запросы и загружает файлы. Когда он запускается, он проверяет расписание и загружает файлы, после того как он делает это один раз, флаг устанавливается в значение false с циклом while на флаге, поэтому поток все еще работает, но ничего не делает, пока этот флаг не будет изменен. Этот флаг boolean newSchedule. По окончании запускается поток для воспроизведения музыки

Способ, которым я сейчас настроил, заключается в том, что мой метод onMessage() в моем слушателе MyTopicClass меняет флаг в загрузчике расписания, чтобы снова начать загрузку расписания. Я вижу это работает от отладки. Получение уведомления вызывает метод getScheduleAgain() в моем классе ScheduleDownloader, который меняет флаг, и мой код снова начинает проверять / загружать расписания. Я вижу, это работает правильно. Что не работает, как я намереваюсь, так это то, что я пытаюсь установить флаг в моем AudioPlayer, чтобы он заканчивался, чтобы я мог начать новый с новым расписанием. Что происходит не так, когда я вызываю setStopFlagToTrue() на моем аудиоплеере внутри моего getScheduleAgain() метода, в соответствии с отладчиком, аудиоплеер имеет значение null?

Таким образом, мой рабочий процесс MyTopic в моем потоке прослушивателя IotClient, когда он получает уведомление, он вызывает onMessage() в моем myTopic, который вызывает мой getScheduleAgain() в моем Scheduledownloader. Это все работает, как задумано, за исключением того, что мой getScheduleAgain() метод вызывает setStopFlagToTrue в моем потоке аудиоплеера, но согласно отладчику это null?

Main.java

      IotClient client = new IotClient("username");
  client.start();

IotClient

     public class IotClient extends Thread {
   Thread t;
   String username;
   ScheduleDownloader downloader;
public IotClient(String username)  {
    this.username = username;
    downloader = new ScheduleDownloader("username,","password2","thread");
}
   public void run(){
    this.currentThread().setPriority(Thread.MAX_PRIORITY);
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
String clientEndpoint = "removed my end point here";       
// replace <prefix> and <region> with your own
String clientId = "1";                              // replace with your own client ID. Use unique client IDs for concurrent connections.

// AWS IAM credentials could be retrieved from AWS Cognito, STS, or other secure sources
AWSIotMqttClient client = new AWSIotMqttClient(clientEndpoint, clientId, "removed credentials ", "removed credentials");

// optional parameters can be set before connect()
try {
    client.connect();
} catch (AWSIotException e) {
    e.printStackTrace();
}
AWSIotQos qos = AWSIotQos.QOS0;
new ScheduleDownloader("dunnesdrogheda","password2","thread").start();
AWSIotTopic topic = new MyTopic("schedule/"+ username, qos,downloader);

try {
    client.subscribe(topic, true);
} catch (AWSIotException e) {
    e.printStackTrace();
}

while(true){
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}
public void start(){
if (t == null) {
    t = new Thread (this, "IotClientThread");
    t.start ();
}
}


  }

MyTopic

public class MyTopic extends AWSIotTopic {
ScheduleDownloader downloader;

public MyTopic(String topic, AWSIotQos qos, ScheduleDownloader downloader) {

    super(topic, qos);
    this.downloader = downloader;
}

@Override
public void onMessage(AWSIotMessage message) {
    System.out.println("Message recieved from topic: "+ message.getStringPayload());
    try {
        downloader.getScheduleAgain();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}
}

ScheduleDownloader, удалены нерелевантные утилиты для скачивания файлов

public class ScheduleDownloader extends Thread {
private Thread t;
private String threadName;

    String username;
    String password;
     volatile boolean newSchedule = true;
     AudioPlayer audioPlayer;

    public ScheduleDownloader(String username,String password,String threadName){
        this.username = username;
        this.password = password;
        this.threadName= threadName;
    }
    public void startPlayerThread(){

    }
    public void startAudioPlayer(Schedule schedule) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        audioPlayer = new AudioPlayer(schedule);
        audioPlayer.start();
    }
 public void start () {
    System.out.println("Starting " +  threadName );
    if (t == null) {
        t = new Thread (this, threadName);
        t.start ();
    }}
public synchronized void run() {
    try {

  while(true){
Thread.sleep(1000);
        while(newSchedule == true) {
            Schedule schedule = null;
            while (schedule == null) {
                System.out.println("Searching for schedule");
                schedule = getTodaysSchedule();
            }
            System.out.println("Schedule Found");
            boolean result = false;
            while (result == false) {
                result = downloadFiles(schedule);
            }
            System.out.println("Files Downloaded");
            startAudioPlayer(schedule);

            newSchedule = false;

         }
       }
    } catch (IOException e) {
        e.printStackTrace();
    }  catch (UnsupportedAudioFileException e) {
        e.printStackTrace();
    } catch (LineUnavailableException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
public void getScheduleAgain() throws InterruptedException {
        this.audioPlayer.setStopFlagToTrue();
        Thread.sleep(4000);
        newSchedule = true;
}

AudioDownloader, checkShouldWePlayAnAdvertisement - это метод, который зацикливается до тех пор, пока для флага завершения не будет установлено значение true

public class AudioPlayer extends Thread {
Long currentFrameMusic;
Long currentFrameAdvertisement;
Clip clipMusic;
Clip clipAdvertisement;
private Thread t;
private volatile boolean stopFlag = false;

// current status of clip
String statusMusic;
String statusAdvertisement;

static AudioInputStream musicInputStream;
static AudioInputStream advertisementInputStream;
static String filePath;
Schedule schedule;

// constructor to initialize streams and clip
public AudioPlayer(Schedule schedule)
        throws UnsupportedAudioFileException,
        IOException, LineUnavailableException
{
    //setup audio stream for music first
    // create AudioInputStream object
this.schedule = schedule;
    appendMusicFiles(schedule);

    // create clip reference
    clipMusic = AudioSystem.getClip();

    // open audioInputStream to the clip
    clipMusic.open(musicInputStream);

    clipMusic.loop(Clip.LOOP_CONTINUOUSLY);
}

public void run(){
    playMusic();
    try {
        checkShouldWePlayAnAdvertisement();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (UnsupportedAudioFileException e) {
        e.printStackTrace();
    } catch (LineUnavailableException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    try {
        checkShouldWePlayAnAdvertisement();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (UnsupportedAudioFileException e) {
        e.printStackTrace();
    } catch (LineUnavailableException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    try {
        checkShouldWePlayAnAdvertisement();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (UnsupportedAudioFileException e) {
        e.printStackTrace();
    } catch (LineUnavailableException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
public void start(){
    t = new Thread (this, "AudioPlayerThread");
    t.start ();
}
public void checkShouldWePlayAnAdvertisement() throws IOException, UnsupportedAudioFileException, LineUnavailableException, InterruptedException {
    ArrayList<String> playedAtTimes = new ArrayList<>();
    ArrayList<Advertisement> advertisementsToBePlayed = new ArrayList<>();
    boolean found;
    //played at times is used to keep track of what time we played advertisements
    //so when the loop reruns and the time hasnt changed it doesnt play it again
    while(stopFlag ==false){
        Thread.sleep(1000);
        found = false;
        ZonedDateTime zdt = ZonedDateTime.now();
        String timeHHMM =zdt.toString().substring(11,16);
        for(int i =0;i<schedule.getAdvertisementScheduleItems().size();i++){
            if(schedule.getAdvertisementScheduleItems().get(i).getTimes().contains(timeHHMM)){
                //this item should be played now
                if(playedAtTimes.contains(timeHHMM)){
                    //we already played this,but the time hasnt changed when the loop ran again
                }else{
                    advertisementsToBePlayed.add(schedule.getAdvertisementScheduleItems().get(i).getAdvertisement());
                    found = true;
                }
            }
        }
        if(found== true) {
            playedAtTimes.add(timeHHMM);
            appendAdvertisementFiles(advertisementsToBePlayed);
            pauseMusic();
            playAdvertisements();
            stopAdvertisement();

            resumeAudioMusic();
        }
    }

    System.out.println("audio player is closing");
 clipMusic.close();
}
public synchronized void setStopFlagToTrue(){
    stopFlag = true;
}

1 Ответ

0 голосов
/ 30 апреля 2018

В IotClient.java вы создали два экземпляра ScheduleDownloader.

public IotClient(String username) {
        this.username = username;
        downloader = new ScheduleDownloader("username,", "password2", "thread");
    }

new ScheduleDownloader("dunnesdrogheda", "password2", "thread").start();
        AWSIotTopic topic = new MyTopic("schedule/" + username, qos, downloader); 

И вы передали 1 экземпляр AWSIotTopic, а другой использовали для порождения потока с while (true)

Экземпляр ScheduleDownloader из MyTopic.java даже не знает о audioPlayer и выдает исключение nullPointerException.

Попробуйте использовать тот же экземпляр ScheduleDownloader ИЛИ определить audioPlayer для общедоступной статики, и он должен работать нормально.

...