最近通过JNI程序写了一个打开、读写串口的代码,发现程序跑起来后CPU资源占用率达到了100%的问题。

代码段如下:

while (pCSerial->m_bReadThreadRuning)
{
        //读取一个串口设备
        length = read(pCSerial->m_hComm, recvBuf, 64);
}

代码逻辑很简单,就是循环去读取串口数据。

解决方法:
增加一个sleep,cpu资源占用率降低到15%左右

while (pCSerial->m_bReadThreadRuning)
{
		usleep(1);
        //读取一个串口设备
        length = read(pCSerial->m_hComm, recvBuf, 64);
}

作用:强制放弃剩下的时间片,让其他线程有机会竞争时间片,从而降低cpu资源占用率。

背景

时间片算法,安卓系统内核CPU的竞争策略是时间片算法;

含义:时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。调度程序所要做的就是维护一张就绪进程列表,当进程用完它的时间片后,它被移到队列的末尾。

原理:既然时间片到了,就会把CPU资源分给其他进程使用,那为啥还会出现CPU资源占用率100%的问题呢?

循环中,哪怕是空的循环进程中虽然没做任何事情,却没有阻塞条件(如sleep),进程一直处于RUNNING状态,也就是说即使该进程时间片到了被切换,该进程还是处于就绪队列,等待下次调度。

优先级越高的进程时间片分配越长,比如你的进程设置了优先级:android:priority=“999”

解决思路:
1、Thread.yield();主动放弃当前线程的时间片
当前线程还是在就绪队列中,而不是在阻塞队列,如果没有其他就绪态的线程,则该线程继续使用。

2、Thread.sleep(0);主动放弃当前线程的时间片,但是只允许优先级相等或者更高的进程使用CPU
当前线程还是在就绪队列中,只允许优先级高的进程使用CPU,没有合适的线程,重新占用CPU

3、Thread.sleep(1);强制放弃当前的时间片,并休息1ms,(实际上可能不止休息1ms)
其他就绪线程竞争时间片,不用在乎优先级。