如何在两个线程之间实时更新共享布尔变量?

时间:2014-08-16 01:14:16

标签: multithreading android-asynctask while-loop

我正在尝试使用循环来调用线程来播放声音。它似乎打电话和玩好。

但是,我希望能够让用户在点击“暂停”时退出循环。按钮。我设置了布尔变量" PauseClicked"允许这个。

我认为我遇到的问题 - 我不知道如何更新" PauseClicked"从我的主线程变量。你知道如何在循环运行的同时从主线程更新这个变量吗?

我们将非常感谢您提供的任何帮助。我花了很多时间没有成功。我不确定的特定代码如下(更新变量的尝试位于第三行):

// Import statements
 public class MyActivity extends Activity {
 boolean PauseClicked = false;

 // .... Other variables and onCreate....


    public void whenPlayClicked(View view) {
        new LongOperation().execute("");

    }

    private class LongOperation extends AsyncTask<String, Void, String> {

 @Override
        protected String doInBackground(String... params) {

            //Setup playing variables
            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            float curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
            float maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
            float leftVolume = curVolume / maxVolume;
            float rightVolume = curVolume / maxVolume;
            int priority = 1;
            int no_loop = 0;
            float normal_playback_rate = 1f;

            //temporary sleep counters
            int blueSleep = (BlueCount * 1000);
            int greenSleep = (GreenCount * 1000);
            int redSleep = (RedCount * 1000);
            int orangeSleep = (OrangeCount * 1000);
            int bellSleep = 4000;
            int cyclesPlayed = 0;

            // Loop - loop until either 1) all cycles have been played. (i.e repeat number of times selected from Spinner).
            //  or 2)Pause button is clicked.
            for (PauseClicked = false; (cyclesPlayed < cycleCount) && (PauseClicked == false); cyclesPlayed++) {
                if (blueSleep > 0) {
                    soundPool.play(blueSoundID, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
                    SystemClock.sleep(blueSleep);
                }

                if (greenSleep > 0) {
                    soundPool.play(greenSoundID, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
                    SystemClock.sleep(greenSleep);
                }

                if (redSleep > 0) {
                    soundPool.play(redSoundID, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
                    SystemClock.sleep(redSleep);
                }

                if (orangeSleep > 0) {
                    soundPool.play(orangeSoundID, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
                    SystemClock.sleep(orangeSleep);
                }
          //      CheckForPause();
            }

            if (TotCount > 0) {
                SystemClock.sleep(bellSleep);
                soundPool.play(bellSoundID, 0.05F, 0.05F, priority, no_loop, normal_playback_rate);
                SystemClock.sleep(bellSleep);
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            textView2.setText("We are returning from call to ASynch task.");
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }


    public void whenPauseClicked(View view) {
        Toast.makeText(getApplicationContext(), "All sounds were paused", Toast.LENGTH_SHORT).show();
        PauseClicked = true;
        soundPool.autoPause();
    }

2 个答案:

答案 0 :(得分:1)

你需要使用AtomicBoolean,在你的情况下使用这种布尔值 - 当多个线程访问它时。 尝试将PauseClicked的定义更改为

AtomicBoolean PauseClicked = new AtomicBoolean(false);

在您的代码中,当您尝试访问它时,请使用它来获取和设置方法。 如果有效,请告诉我。

答案 1 :(得分:0)

在这种情况下,

volatile应该没问题,除非您正在执行复合操作(但是,我没有看到任何,但您可能希望在某些您未提供的代码中使用它们),例如正如AtomicBoolean中提供的那些,您将使用它们。

由于易失性布尔值保证原子写入和读取,因此应该设置它。它们略微比AtomicBoolean快,但差别小于1纳秒,这可以忽略不计。