Как разделить объект между двумя потоками (синхронизация потоков)?

У меня два потока. Один записывает аудиоданные в переменную. Другой поток отправляет эту записанную переменную на сервер. Что мне нужно делать с точки зрения параллелизма, поскольку я новичок в многопоточности?

Ниже приведен фрагмент кода:

short[] sData = new short[1024]; recordingThread = new Thread(new Runnable() { public void run() { android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); while (isRecording) { recorder.read(sData, 0, BufferElements2Rec); } } }, "AudioRecorder Thread"); recordingThread.start(); 

И другой поток, который обращается к тем же sData и отправляет его на сервер:

 Thread sendThread= new Thread(new Runnable() { public void run() { android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); while (true) { try { ByteBuffer.wrap(bData).order(ByteOrder.LITTLE_ENDIAN) .asShortBuffer().put(sData); } } }); 

На ваш вопрос есть два аспекта.

  • Предполагая, что sData является локальной переменной, все, что вам нужно сделать, чтобы получить две потоки для совместного использования массива, – объявить sData final . (И если sData является переменной экземпляра или класса, вам даже не нужно это делать …)

  • Получение двух потоков для совместного использования массива – это немного сложнее. Проблема в том, что эти два потока необходимо синхронизировать. Поток отправки должен знать, в какой части массива, на который записал поток записей. Кроме того, синхронизация необходима для обеспечения того, чтобы данные, записанные потоком записи, были видны в потоке отправки.

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


Но то, что вы делаете на семантическом уровне, выглядит так, как будто оно должно работать как классический круговой буфер short значений. Поэтому я бы рекомендовал искать существующую реализацию, которую вы можете повторно использовать. (Например, если вы готовы взять накладные расходы Short или short вы можете использовать ArrayBlockingQueue<Short> .)

Чтобы свести к минимуму переосмысление колеса, вы можете реализовать его как синхронизацию производителя / потребителя. Для начинающих:

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ArrayBlockingQueue.html

На всякий случай, некоторые вводные вещи здесь:

http://en.wikipedia.org/wiki/Producer-consumer_problem

Один из способов справиться с этим – использовать защелку, если это однократная операция или CyclicBarrier, если это необходимо повторить.