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
本文转自jiahuafu博客园博客,原文链接http://www.cnblogs.com/jiahuafu/p/6855568.html如需转载请自行联系原作者

jiahuafu

相关文章
|
3天前
|
设计模式 安全 Java
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
|
1天前
|
消息中间件 监控 安全
【JAVAEE学习】探究Java中多线程的使用和重点及考点
【JAVAEE学习】探究Java中多线程的使用和重点及考点
|
1天前
|
安全 Java 开发者
构建高效微服务架构:后端开发的新范式Java中的多线程并发编程实践
【4月更文挑战第29天】在数字化转型的浪潮中,微服务架构已成为软件开发的一大趋势。它通过解耦复杂系统、提升可伸缩性和促进敏捷开发来满足现代企业不断变化的业务需求。本文将深入探讨微服务的核心概念、设计原则以及如何利用最新的后端技术栈构建和部署高效的微服务架构。我们将分析微服务带来的挑战,包括服务治理、数据一致性和网络延迟问题,并讨论相应的解决方案。通过实际案例分析和最佳实践的分享,旨在为后端开发者提供一套实施微服务的全面指导。 【4月更文挑战第29天】在现代软件开发中,多线程技术是提高程序性能和响应能力的重要手段。本文通过介绍Java语言的多线程机制,探讨了如何有效地实现线程同步和通信,以及如
|
3天前
|
安全 Java
【JAVA】线程的run()和start()有什么区别?
【JAVA】线程的run()和start()有什么区别?
|
4天前
|
缓存 Java
Java并发编程:深入理解线程池
【4月更文挑战第26天】在Java中,线程池是一种重要的并发工具,它可以有效地管理和控制线程的执行。本文将深入探讨线程池的工作原理,以及如何使用Java的Executor框架来创建和管理线程池。我们将看到线程池如何提高性能,减少资源消耗,并提供更好的线程管理。
|
5天前
|
Java UED
Java并发编程:理解并应用线程池
【4月更文挑战第25天】在处理并发问题时,线程池是Java中一种重要的工具。本文将探讨线程池的概念、优势以及如何在Java程序中有效地使用它。我们将详细解释线程池的工作原理,并通过示例来使其更加易于理解。
|
5天前
|
监控 Java 调度
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
Java多线程实战-从零手搓一个简易线程池(四)线程池生命周期状态流转实现
|
5天前
|
设计模式 Java
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现
Java多线程实战-从零手搓一个简易线程池(三)线程工厂,核心线程与非核心线程逻辑实现
|
5天前
|
Java 测试技术
Java多线程实战-从零手搓一个简易线程池(二)线程池实现与拒绝策略接口定义
Java多线程实战-从零手搓一个简易线程池(二)线程池实现与拒绝策略接口定义
|
5天前
|
存储 安全 Java
Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列
Java多线程实战-从零手搓一个简易线程池(一)定义任务等待队列