java用while循环设计轮询线程的性能问题
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
java用while循环设计轮询线程的性能问题的更多相关文章
- 基于springboot实现轮询线程自动执行任务
本文使用: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时 ...
- 为什么JAVA要提供 wait/notify 机制?是为了避免轮询带来的性能损失
wait/notify 机制是为了避免轮询带来的性能损失. 为了说清道理,我们用“图书馆借书”这个经典例子来作解释. 一本书同时只能借给一个人.现在有一本书,图书馆已经把这本书借了张三. 在简单的s ...
- Java实现负载均衡算法--轮询和加权轮询
1.普通轮询算法 轮询(Round Robin,RR)是依次将用户的访问请求,按循环顺序分配到web服务节点上,从1开始到最后一台服务器节点结束,然后再开始新一轮的循环.这种算法简单,但是没有考虑到每 ...
- Apollo 3 定时/长轮询拉取配置的设计
前言 如上图所示,Apollo portal 更新配置后,进行轮询的客户端获取更新通知,然后再调用接口获取最新配置.不仅仅只有轮询,还有定时更新(默认 5 分钟一次).目的就是让客户端能够稳定的获取到 ...
- Java实现平滑加权轮询算法--降权和提权
上一篇讲了普通轮询.加权轮询的两种实现方式,重点讲了平滑加权轮询算法,并在文末留下了悬念:节点出现分配失败时降低有效权重值:成功时提高有效权重值(但不能大于weight值). 本文在平滑加权轮询算法的 ...
- 如何从线程返回信息——轮询、回调、Callable
考虑有这样一个LiftOff类: /** * 类LiftOff.java的实现描述:显示发射之前的倒计时 * * @author wql 2016年9月21日 下午1:46:46 */ public ...
- 权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现2
权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现 ----参考Nginx中负载均衡算法实现 与上一遍博客 http://www.cnblogs.com/hu ...
- 权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现
权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现 import java.math.BigInteger; import java.util.ArrayLi ...
- [置顶] Android AlarmManager实现不间断轮询服务
在消息的获取上是选择轮询还是推送得根据实际的业务需要来技术选型,例如对消息实时性比较高的需求,比如微博新通知或新闻等那就最好是用推送了.但如果只是一般的消息检测比如更新检查,可能是半个小时或一个小时一 ...
随机推荐
- react native 获取 软键盘高度 和 新增软键盘的组件
import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View, Keyboard, Te ...
- excel 应用,右下角的小十字拖拽的时候形成递减的数列
excel 应用,右下角的小十字拖拽的时候形成递减的数列 2012-12-20 15:16无良小鬼 | 浏览 352 次 比如说我想要这样一列数字201220112010……这样递减的数列,而不是递增 ...
- 捕捉过滤器(CaptureFilters)和显示过滤器(DisplayFilters)--Wireshark
Wireshark的基本使用——过滤器 前言 网络上关于Wireshark的教程已有不少,博主就简单介绍一下Wireshark分析数据包时最重要的技巧之一的过滤器..一次性嗅探到的数据包有很多,想要高 ...
- YAML文件格式入门
YAML快速入门 https://www.jianshu.com/p/97222440cd08 https://yaml.org/spec/1.2/spec.pdf http://nodeca.git ...
- bootstrap table教程--后台数据绑定、特殊列处理、排序
上一篇文章介绍了基本的使用教程.本节主要介绍Bootstrap的后台数据绑定.特殊列处理及列的排序功能 1.数据绑定 一般做程序设计,很少是使用json文件直接绑定数据.基本上我们都是使用编程语言进行 ...
- Tiny4412 u-boot分析(3)u-boot 引导内核流程
在u-boot中,通过bootm命令启动内核.bootm命令的作用是将内核加载到指定的内存地址,然后通过R0.R1.R2寄存器传递启动参数之后启动内核.在启动内核之前需要对环境做一些初始化工作,主要有 ...
- nats 学习 request/reply 模式基本使用
nats 一个云原生的消息系统,使用简单,客户端丰富,支持的模式是pub/sub 但是集成比较灵活,可以支持loadblance, request/reply pub/sub 代码演示的是reques ...
- 华硕主板P8H61(P8H61-M_LX3_PLUS_R2.0)成功禁用USB口
公司大批这个型号的主板,在百度上搜索了一下,其中有一篇帖子说华硕客服说这个型号的USB控制XX是集成成南桥上面没法禁止. 经过研究发现官网上的0802版可以支持禁止usb,并且可以根据需要为每一个US ...
- Java ScriptEngine 解析js
Java ScriptEngine 解析js 1.脚本引擎 ① 通过脚本名称获取: ScriptEngine engine = new ScriptEngineManager().getEn ...
- 设置putty标题栏显示固定信息
设置好后,登录服务器后,发现标题栏又显示root@sit:/opt/ihome,没有显示成我设置的title内容.原因是: 在Terminal->Features中一定要勾选Disable re ...