在用自定義線程池的時候,遇到cpu100%,經過驗證後,發現問題來源於我定義的子線程。
子線程的主要功能是從任務隊列(LinkedBlockingQueue)裏面持續拿出任務,並且執行。
以下爲令CPU100的代碼。
private class WorkThread extends Thread
{
@Override
public void run()
{
while(flag)
{
Runnable task=null;
if(flag&&!taskQueue.isEmpty())//當隊列非空
{
try
{
task=taskQueue.poll();//拿到任務,若沒有則拿到null
if(task!=null)
task.run();//執行任務
} catch (Exception e)
{
e.printStackTrace();
}
}
}
}
}
之後,隨便往while循環裏面添加進System.out.println(“xxxx”);
發現CPU降低了,不會升到100,於是我修改了代碼如下:
//增加一句Thread.sleep(),令所有線程每次進入while循環的時候,都先休眠釋放資源,這CPU就不會升到100
private class WorkThread extends Thread
{
@Override
public void run()
{
while(flag)
{
try {
Thread.sleep((long) 0.5);//先釋放資源,避免cpu佔用過高
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Runnable task=null;
if(flag&&!taskQueue.isEmpty())//當隊列非空
{
try
{
task=taskQueue.poll();//拿到任務,若沒有則拿到null
if(task!=null)
task.run();//執行任務
} catch (Exception e)
{
e.printStackTrace();
}
}
}
}
}
造成上述現象的原因:LinkedBlockingQueue是線程安全,當多線程同步從隊列裏面取出任務,在微觀時刻,有且只有一個線程能進入隊列中取,因此其他線程阻塞等待,此時各線程都持有cpu資源,不釋放,
就造成了大量cpu等待,因而CPU會升高;
值得注意的一點:
LinkedBlockingQueue中取出任務方法有幾種,比如take(),poll(),一開始我用take方法,發現運行後,線程資源無法得到釋放,後來看了api發現take()是阻塞拿,意思是:線程往隊列裏面拿任務,
如果隊列裏面沒有任務,則進行等待知道有任務再次喚醒。
而poll()方法則是有任務就拿,沒任務就返回null,因此不會出現阻塞等待,若上面代碼改成用take方法,同樣會出現cpu100的問題,也在於阻塞,同時也會出現線程不被GC回收。
---------------------
作者:Tardis1
來源:CSDN
原文:https://blog.csdn.net/tardis1/article/details/51693196
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!