runnable, thread, handler

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 是一一对应的关系。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值