runnalbe 是个啥?
package java.lang;
@FunctionalInterface
public interface Runnable {
void run();
}
只是一个interface而已
class RecordThread implements Runnable {
public void startRecording() {
// getMinBufferSize is a class static method
audioBufSize = AudioRecord.getMinBufferSize(
audio_sample_rate,
audio_format_channel,
AudioFormat.ENCODING_PCM_16BIT);
if (null == audioRecord) {
//hot point
setForceUseByAudioSystem();// for media
audioRecord = new AudioRecord(audio_source,
audio_sample_rate,
audio_format_channel,
AudioFormat.ENCODING_PCM_16BIT,
audioBufSize);
}
new Thread(this).start();
}
public void run() {
System.out.println(LOG + "audioRecord startRecording()");
audioRecord.startRecording();
System.out.println(LOG + "start recording");
final byte[] data = new byte[audioBufSize];
this.isRecording = true;
while (this.isRecording && audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
//读取采集数据到缓冲区中,read就是读取到的数据量
final int read = audioRecord.read(data, 0, audioBufSize);
if (AudioRecord.ERROR_INVALID_OPERATION != read)
//将数据写入到文件中
{
try {
dataOutputStream.write(data, 0, read);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Thread一个构造函数的接口是:也就是对应上面的 new Thread(This)
public Thread(Runnable var1) {
this.init((ThreadGroup)null, var1, "Thread-" + nextThreadNum(), 0L);
}
也就是说Runnable 是个用户需要实现的接口,以这个实现的接口为参数实现为一个Thread, 而这个Thread 的执行体正是 run 函数的实现。
Native thread
class Thread : virtual public RefBase
{
public:
// Create a Thread object, but doesn't create or start the associated
// thread. See the run() method.
explicit Thread(bool canCallJava = true);
virtual ~Thread();
// Start the thread in threadLoop() which needs to be implemented.
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t run( const char* name,
int32_t priority = PRIORITY_DEFAULT,
size_t stack = 0);
private:
// Derived class must implement threadLoop(). The thread starts its life here.
virtual bool threadLoop() = 0;
}
Native Looper
/**
* For callback-based event loops, this is the prototype of the function
* that is called when a file descriptor event occurs.
* It is given the file descriptor it is associated with,
* a bitmask of the poll events that were triggered (typically EVENT_INPUT),
* and the data pointer that was originally supplied.
*
* Implementations should return 1 to continue receiving callbacks, or 0
* to have this file descriptor and callback unregistered from the looper.
*/
typedef int (*Looper_callbackFunc)(int fd, int events, void* data);
/**
* A message that can be posted to a Looper.
*/
struct Message {
Message() : what(0) { }
Message(int w) : what(w) { }
/* The message type. (interpretation is left up to the handler) */
int what;
};
/**
* Interface for a Looper message handler.
*
* The Looper holds a strong reference to the message handler whenever it has
* a message to deliver to it. Make sure to call Looper::removeMessages
* to remove any pending messages destined for the handler so that the handler
* can be destroyed.
*/
class MessageHandler : public virtual RefBase {
protected:
virtual ~MessageHandler();
public:
/**
* Handles a message.
*/
virtual void handleMessage(const Message& message) = 0;
};
Looper_poolOnce的返回值
enum {
/**
* Result from Looper_pollOnce() and Looper_pollAll():
* The poll was awoken using wake() before the timeout expired
* and no callbacks were executed and no other file descriptors were ready.
*/
POLL_WAKE = -1,
/**
* Result from Looper_pollOnce() and Looper_pollAll():
* One or more callbacks were executed.
*/
POLL_CALLBACK = -2,
/**
* Result from Looper_pollOnce() and Looper_pollAll():
* The timeout expired.
*/
POLL_TIMEOUT = -3,
/**
* Result from Looper_pollOnce() and Looper_pollAll():
* An error occurred.
*/
POLL_ERROR = -4,
};
Flags for file descriptor events that a looper can monitor
/**
* Flags for file descriptor events that a looper can monitor.
*
* These flag bits can be combined to monitor multiple events at once.
*/
enum {
/**
* The file descriptor is available for read operations.
*/
EVENT_INPUT = 1 << 0,
/**
* The file descriptor is available for write operations.
*/
EVENT_OUTPUT = 1 << 1,
/**
* The file descriptor has encountered an error condition.
*
* The looper always sends notifications about errors; it is not necessary
* to specify this event flag in the requested event set.
*/
EVENT_ERROR = 1 << 2,
/**
* The file descriptor was hung up.
* For example, indicates that the remote end of a pipe or socket was closed.
*
* The looper always sends notifications about hangups; it is not necessary
* to specify this event flag in the requested event set.
*/
EVENT_HANGUP = 1 << 3,
/**
* The file descriptor is invalid.
* For example, the file descriptor was closed prematurely.
*
* The looper always sends notifications about invalid file descriptors; it is not necessary
* to specify this event flag in the requested event set.
*/
EVENT_INVALID = 1 << 4,
};
Looper 构造函数
Looper::Looper(bool allowNonCallbacks)
: mAllowNonCallbacks(allowNonCallbacks),
mSendingMessage(false),
mPolling(false),
mEpollRebuildRequired(false),
mNextRequestSeq(0),
mResponseIndex(0),
mNextMessageUptime(LLONG_MAX) {
mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
AutoMutex _l(mLock);
rebuildEpollLocked();
}
void Looper::rebuildEpollLocked() {
// Allocate the new epoll instance and register the wake pipe.
mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeEventFd.get();
int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, mWakeEventFd.get(), &eventItem);
for (size_t i = 0; i < mRequests.size(); i++) { //mRequests是什么时候赋值的?
const Request& request = mRequests.valueAt(i);
struct epoll_event eventItem;
request.initEventItem(&eventItem);
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
}
}
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
Request request;
request.fd = fd;
request.ident = ident; //POLL_CALLBACK
request.events = events;
request.seq = mNextRequestSeq++;
request.callback = callback;
request.data = data;
int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);
mRequests.add(fd, request);
}
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
pollInner(timeoutMillis);
}
int Looper::pollInner(int timeoutMillis) {
// Invoke pending message callbacks.
mNextMessageUptime = LLONG_MAX;
while (mMessageEnvelopes.size() != 0) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
if (messageEnvelope.uptime <= now) {
// Remove the envelope from the list.
// We keep a strong reference to the handler until the call to handleMessage
// finishes. Then we drop it so that the handler can be deleted *before*
// we reacquire our lock.
{ // obtain handler
sp<MessageHandler> handler = messageEnvelope.handler;
Message message = messageEnvelope.message;
mMessageEnvelopes.removeAt(0);
mSendingMessage = true;
mLock.unlock();
handler->handleMessage(message);
} // release handler
mLock.lock();
mSendingMessage = false;
result = POLL_CALLBACK;
} else {
// The last message left at the head of the queue determines the next wakeup time.
mNextMessageUptime = messageEnvelope.uptime;
break;
}
}
}
MessageHandler and Message
在sendMessage时引入了MessageHandler
void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
sendMessageAtTime(now, handler, message);
}
void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,
const Message& message) {
MessageEnvelope messageEnvelope(uptime, handler, message);
mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
}
Thread 与 Looper
前文有提到,线程默认是没有消息循环的,需要调用 Looper.prepare() 来达到目的,那么我们对这个问题的探索就从 Looper.prepare() 开始, looper使线程具有消息循环功能, 一个线程只能有一个looper.
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
Looper 与 MessageQueue
直接来看源码:
public final class Looper {
// ...
final MessageQueue mQueue;
// ...
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
// ...
}
}
Looper 对象里有一个 MessageQueue 类型成员,在构造的时候 new 出的,并且它是一个 final,没有地方能修改它的指向。
小结: Looper 与 MessageQueue 是一一对应的关系。