什么可能导致java进程逐渐减少CPU的份额?

时间:2012-12-12 23:32:26

标签: java linux jvm

我有一个非常简单的java程序,打印出100万个随机数。在linux中,我观察了该程序在其生命周期中所占的%CPU,它从98%开始然后逐渐降低到2%,从而导致程序非常慢。有哪些因素可能导致程序逐渐减少CPU时间?

我已尝试使用nice -20运行它,但我仍然看到相同的结果。

编辑:用/usr/bin/time -v运行程序我看到异常数量的非自愿上下文切换(588自愿与16478非自愿),这表明操作系统正在让其他更高优先级的进程运行。

4 个答案:

答案 0 :(得分:1)

归结为两件事:

  • I / O很贵,而且
  • 根据您在进行中存储数字的方式,这也会对性能产生负面影响。

如果你主要在循环中做System.out.println(randInt)一百万次,那么这会花费很多。 I / O不是免费提供的东西之一,写入任何输出流都需要资源。

答案 1 :(得分:0)

我首先要通过JConsole或VisualVM进行分析,看看它在CPU%较低时的实际操作情况。正如评论中提到的那样,它很有可能阻塞,例如:等待IO(用户输入,SQL查询需要很长时间等)

答案 2 :(得分:0)

如果您的应用程序受I / O限制 - 例如等待来自网络调用的响应,或磁盘读/写

答案 3 :(得分:0)

如果你想尝试平衡一切,你应该创建一个队列来保存要打印的数字,然后让一个线程生成它们(生产者),另一个线程读取并打印它们(消费者)。这可以通过LinkedBlockingQueue轻松完成。

public class PrintQueueExample {

    private BlockingQueue<Integer> printQueue = new LinkedBlockingQueue<Integer>();

    public static void main(String[] args) throws InterruptedException {
        PrinterThread thread = new PrinterThread();
        thread.start();
        for (int i = 0; i < 1000000; i++) {
            int toPrint = ...(i) ;
            printQueue.put(Integer.valueOf(toPrint));
        }
        thread.interrupt();
        thread.join();
        System.out.println("Complete");
    }

    private static class PrinterThread extends Thread {

        @Override
        public void run() {
            try {
                while (true) {
                    Integer toPrint = printQueue.take();
                    System.out.println(toPrint);
                }
            } catch (InterruptedException e) {
                // Interruption comes from main, means processing numbers has stopped
                // Finish remaining numbers and stop thread
                List<Integer> remainingNumbers = new ArrayList<Integer>();
                printQueue.drainTo(remainingNumbers);
                for (Integer toPrint : remainingNumbers)
                    System.out.println(toPrint);
            }
        }
    }
}

此代码可能存在一些问题,但这是它的要点。