java用while循环设计轮询线程的性能问题
2024-08-27 05:31:24
java用while循环设计轮询线程的性能问题
轮询线程在开发过程中的应用是比较广泛的,在这我模拟一个场景,有一个队列和轮询线程,主线程往队列中入队消息,轮询线程循环从队列中读取消息并打印消息内容。有点类似Android中Handler发送消息。
首先定义一个Message类。
public class Message {
private String content;
public Message(String content)
{
this.content=content;
}
public void display(){
System.out.println(content);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
这个类很简单,在构造的时候传入消息内容,display()方法输出打印消息内容。
接下来定义一个轮询线程,一开始蠢萌的我这么写
public class PollingThread extends Thread implements Runnable {
public static Queue<Message> queue = new LinkedTransferQueue<Message>();
@Override
public void run() {
while (true) {
while (!queue.isEmpty()) {
queue.poll().display();
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
这个轮询线程功能很简单,一直不停的轮询队列,一旦队列中有消息进入,就将它出队并调用display()方法输出内容。
接下来在Main()方法中循环创建消息将它放入队列
public class Main {
public static void main(String[] args){
PollingThread pollingThread=new PollingThread();
pollingThread.start();
int i=1;
while(true)
{
PollingThread.queue.offer(new Message("新消息"+i));
i++;
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
运行结果
新消息1
新消息2
新消息3
新消息4
新消息5
新消息6
新消息7
新消息8
新消息9
新消息10
新消息11
新消息12
新消息13
新消息14
新消息15
......
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
虽然这么做,功能是实现了,可是我们来看下cpu占用率
程序刚编译启动的时候cpu占用率到了100%,开始运行后一直处于44%左右。这个占用率还是比较高的,那么我们来分析一下这个轮询线程,假设一直没有消息入队,或者消息入队的间隔时间比较长的话,它就会循环的去执行while(!queue.isEmpty())判断队列是否为空,其实这个判断操作是非常耗性能的。我们应该把这个轮询线程设计的更合理一点。那么怎样设计比较合理呢?既然循环对队列判空是比较浪费性能的操作,那么我们如果可以让这个轮询线一开始处于阻塞状态,主线程在每次入队消息的时候通知轮询线程循环出队输出消息内容,当队列为空的时候轮询线程又自动的进入阻塞状态,就可以避免轮询线程死循环对队列判空。接下来我们改造一下轮询线程和主线程的代码
public class PollingThread extends Thread implements Runnable {
public static Queue<Message> queue = new LinkedTransferQueue<Message>();
@Override
public void run() {
while (true) {
while (!queue.isEmpty()) {
queue.poll().display();
}
//把队列中的消息全部打印完之后让线程阻塞
synchronized (Lock.class)
{
try {
Lock.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
public class Main {
public static void main(String[] args){
PollingThread pollingThread=new PollingThread();
pollingThread.start();
int i=1;
while(true)
{
PollingThread.queue.offer(new Message("新消息"+i));
i++;
//有消息入队后激活轮询线程
synchronized (Lock.class)
{
Lock.class.notify();
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
这时候再来运行一下
运行结果
新消息1
新消息2
新消息3
新消息4
新消息5
新消息6
新消息7
新消息8
新消息9
新消息10
新消息11
......
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
再来看看cpu占用率
轮询线程经过改造后cpu占用率基本稳定在11%,比之前44%下降了不少。
所以,在编写轮询线程的时候,尽量用通知的方式去让轮询线程执行操作,避免重复的条件判断造成的性能浪费。
http://blog.csdn.net/q15858187033/article/details/60583631
最新文章
- IntelliJ IDEA - 热部署插件JRebel 安装使用教程
- .NET面试题系列[9] - IEnumerable
- c语言迷宫游戏的实现
- C# ADO.NET (sql语句连接方式)(查询)
- mfc通过消息传递参数进行程序间通信
- IEnumerable和List有什么区别?
- iOS之UIAlertView的使用
- C#实现DNS解析服务
- Bonferroni校正法
- java中计算两个时间差
- java排序算法(十):桶式排序
- mysql实现多实例
- script标签
- POJ1236 Network of Schools【强连通】
- Jumpserver堡垒机
- python中的sockeserver模块简单实用
- (原创)拨开迷雾见月明-剖析asio中的proactor模式(二)
- 相邻行列相互影响的状态类问题(类似状压dp的搜索)(POJ3279)
- WebDriver高级应用实例(1)
- SpringMVC初写(三)Controller的生命周期
热门文章
- java并发编程之一--Semaphore的使用
- 词云:解决pip install wordcloud安装过程中报错“error: command &#39;x86_64-linux-gnu-gcc&#39; failed with exit status 1”问题
- Winform开发之ADO.NET对象Connection、Command、DataReader、DataAdapter、DataSet和DataTable简介
- [转载]MySQL索引原理与慢查询优化
- 专业软件 —— Adobe Audition
- [QT]加快qt编译:设置默认多核编译qt
- springboot整合mybatis增删改查(二):springboot热部署
- 前后端分离之让前端开发脱离接口束缚(mock)
- TCP拥塞控制机制
- TypeScript学习笔记(三) - 方法