Java线程:CPU利用率过高

Java线程:CPU利用率过高,java,multithreading,cpu-usage,Java,Multithreading,Cpu Usage,我正在使用一项服务,它从卡夫卡读入信息,并将其推入卡桑德拉 我也在使用线程架构 有人说,k个线程使用卡夫卡主题。它们写入队列,声明为: public static BlockingQueue<> content是用于读写操作的阻塞队列 我在线程化的实现中扩展了Thread类,有固定数量的线程继续执行,除非被中断 问题是,这占用了太多的CPU。下面是top命令的第一行: PID USER PR NI VIRT RES SHR S %CPU %MEM

我正在使用一项服务,它从卡夫卡读入信息,并将其推入卡桑德拉

我也在使用线程架构

有人说,
k个线程
使用卡夫卡主题。它们写入队列,声明为:

public static BlockingQueue<>
content
是用于读写操作的阻塞队列

我在线程化的实现中扩展了
Thread
类,有固定数量的线程继续执行,除非被中断

问题是,这占用了太多的CPU。下面是
top
命令的第一行:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
46232 vishran+  20   0 3010804 188052  14280 S 137.8  3.3   5663:24 java
以下是此进程线程上的
strace
输出:

strace -t -p 46322
Process 46322 attached
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
15:18:47 sched_yield()                  = 0
....and so on
我之所以使用
Thread.yield()
,是因为

如果您需要任何其他调试信息,请告诉我


现在的问题是,如何将CPU利用率降至最低?

从代码的外观来看,用户线程似乎总是在检查可用的内容。因此,您的线程总是在运行并且从不IDLE(等待别人通知他们),因此您的CPU总是在做一些事情,即使它总是将线程生成为当前线程

while(!Thread.currentThread().isInterrupted()){
螺纹屈服强度();
如果(!content.isEmpty()){

很明显,您正试图解决我们许多人在编程生涯中遇到的生产者-消费者问题

您当前正在做的是让消费者主动不断地检查是否有东西要消费

解决此问题的CPU密集型方法最少且最简单:

  • 让生产商向消费者发出信号,说明它已经生产了一些东西

  • 签出,因为它包含一种最简单的方法。您可能需要重新访问以获得更深入的帮助。

    阻塞队列的全部目的是在它为空时阻塞。因此,使用者线程(填充到Cassandra中的线程)不必手动检查它们是否为空。您只需调用take()如果队列为空,则调用将被阻止,除非它被中断或存在可用元素

    当一个线程被阻塞时,调度程序可以在其位置调度其他线程,从而避免您调用yield()等。请记住,只有当优先级大于或等于正在生成的线程的线程可供运行时,yield()才会让位给另一个线程

    public void run(){
        LOGGER.log(Level.INFO, "Thread Created: " +Thread.currentThread().getName());
        try {
                JSONObject msg = content.take();
                // JSON
                for(String tableName : tableList){
                    CassandraConnector.getSession().execute(createQuery(tableName, msg));
                }
         } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
         }
    }
    

    如其他答案中所述,您正在执行忙等待,而不是使用
    内容
    阻止队列的中心功能:等待下一个条目并将其从队列中删除。这是使用
    take()
    方法完成的:

    while (!Thread.currentThread().isInterrupted()) {
        try {
            JSONObject msg = content.take();
            for(String tableName : tableList){
                CassandraConnector.getSession().execute(createQuery(tableName, msg));
            }
        } catch (Exception e) {
    
        }
    }
    

    @vish4071您应该使用
    阻塞队列
    ,因为它是为使用而设计的:使用一种阻塞方法:或者您可以为此添加一个代码片段。我将在@Robert的答案中尝试阻塞。谢谢..还有一件事…将
    .take()
    弹出元素?最后一件事。
    现在不需要收益率了吗?如果不需要,你能告诉原因吗?为什么我们不使用
    isInterrupted()
    检查?是收益率()不再是我上面回答中提到的要求。take()是一个阻塞调用,它将线程设置为阻塞状态,因此不会消耗任何资源。调度程序负责调度其他可供运行的线程。那么
    isInterrupted()
    check呢?这将运行一次并执行一个查询…此线程将死亡…不是吗?
    while (!Thread.currentThread().isInterrupted()) {
        try {
            JSONObject msg = content.take();
            for(String tableName : tableList){
                CassandraConnector.getSession().execute(createQuery(tableName, msg));
            }
        } catch (Exception e) {
    
        }
    }