【问题标题】:Multithreading in JFreeChart with SimpleDateFormatJFreeChart 中的多线程与 SimpleDateFormat
【发布时间】:2014-03-03 14:54:58
【问题描述】:

我正在开发一个连接到远程服务器并获取 i/o 速率的监控程序。这是我的代码:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimePeriod;
import org.jfree.data.time.TimeTableXYDataset;


public class IOStat extends JPanel implements Runnable {

    FileRW FRW;
    Sessionn SES;
    String SONUC;
    String SUTUN;
    String[] st;
    int SECIM; 
    int NODE; 
    private static final int COUNT = 650;
    String deger;
     String[] degerler;

    Timer timer;
    String TITLE;
    private static String Y_EKSEN;
    private static String X_EKSEN;
    String SUTUNLAR = null;
    int i;
    int sayac;
    Thread t;
    TimeTableXYDataset dataset;

    public IOStat(String title, String yEksen, String xEksen, Sessionn obj, int node, String[] label) {
        SES = new Sessionn();
        SES.girisYap(obj.USERNAME, obj.PASSWORD, obj.HOSTNAME);
        this.setLayout(new GridLayout());
        t = new Thread(this, title);
        i = 0;
        sayac = label.length;
        NODE = node;
        SES = obj;
        Y_EKSEN = yEksen;
        X_EKSEN = xEksen;
        TITLE = title;
        st = label;
        dataset = new TimeTableXYDataset();
        JFreeChart chart = createAreaChart(dataset);
        this.add(new ChartPanel(chart), BorderLayout.CENTER);
        t.start();
    }

    private JFreeChart createAreaChart(TimeTableXYDataset dataset) {
       JFreeChart chart = ChartFactory.createStackedXYAreaChart(
                TITLE, X_EKSEN, Y_EKSEN, dataset, PlotOrientation.VERTICAL, true, true, false);
        DateAxis domainAxis = new DateAxis();
        domainAxis.setAutoRange(true);
        domainAxis.setDateFormatOverride(new ThreadSafeSimpleDateFormat("HH:mm"));
        domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.MINUTE, 5));
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setDomainAxis(domainAxis);
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        ValueAxis axis = plot.getDomainAxis();
        axis.setAutoRange(true);
        axis.setFixedAutoRange(3600000.0); //1 saat
        rangeAxis.setNumberFormatOverride(new DecimalFormat("#,###.########"));
        rangeAxis.setAutoRange(true);
        return chart;
    }

    public void run() {
        try {
            while (true) {
                  TimePeriod  period = new Second();
              deger = SES.sorguCalistir("ssh " + TITLE + " iostat -k -x 1 2 | perl -e 'local $/=\"\"; @p=<STDIN>; print @p[4];' | awk '{ print $6 \" \" $7}' | grep -v rsec |awk '{ SUM += $1; SUM2 += $2} END { print SUM \" \" SUM2 }'");
               degerler=null;
              degerler = deger.split(" ");
                for (int j = 0; j < 2; j++) {

                    dataset.add(period, Double.parseDouble(degerler[j]), st[j]);
                    if (dataset.getItemCount() > COUNT) {
                        TimePeriod firstItemTime = dataset.getTimePeriod(0);
                        dataset.remove(firstItemTime, st[j]);
                    }
                }

                Thread.sleep(1000);
            }
        } catch (InterruptedException ex) {
            Logger.getLogger(IOStat.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public static void main(final String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {

            }
        });
    }
}

当我运行此代码时,它在开始时运行良好,但在两秒钟后,数据集值中出现了某种数据损坏。我的字符串数组degerler 随机获得不应该的不同值。我还听说 SimpleDateFormat 不是线程安全的。但是为了解决这个问题,我的periodrun() 函数中被创建为局部变量,正如你在我的代码中看到的那样。

异常如下:

Exception in thread "alzproddbadm02" java.lang.NumberFormatException: For input string: "0
0"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
    at java.lang.Double.parseDouble(Double.java:540)
    at OsWatch.IOStat.run(IOStat.java:107)
    at java.lang.Thread.run(Thread.java:744)
Exception in thread "alzproddbadm01" java.lang.NumberFormatException: For input string: "0
0"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
    at java.lang.Double.parseDouble(Double.java:540)
    at OsWatch.IOStat.run(IOStat.java:107)
    at java.lang.Thread.run(Thread.java:744)
Mar 03, 2014 4:53:27 PM OsWatch.IOStat run
SEVERE: null
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at OsWatch.IOStat.run(IOStat.java:114)
    at java.lang.Thread.run(Thread.java:744)

当我将deger 值放到控制台并跟踪它时,输出如下:

run:
deger=
deger=
Exception in thread "alzproddbadm02" Exception in thread "alzproddbadm01" java.lang.NumberFormatException: empty String
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1011)
    at java.lang.Double.parseDouble(Double.java:540)
    at OsWatch.IOStat.run(IOStat.java:108)
    at java.lang.Thread.run(Thread.java:744)
java.lang.NumberFormatException: empty String
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1011)
    at java.lang.Double.parseDouble(Double.java:540)
    at OsWatch.IOStat.run(IOStat.java:108)
    at java.lang.Thread.run(Thread.java:744)
deger=0 0

deger=0 0

deger=0 468

deger=0 468
0 1764

Exception in thread "alzproddbadm04" java.lang.NumberFormatException: For input string: "468
0"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
    at java.lang.Double.parseDouble(Double.java:540)
    at OsWatch.IOStat.run(IOStat.java:108)
    at java.lang.Thread.run(Thread.java:744)
deger=0 0

deger=0 1104

deger=0 0

deger=0 0

deger=0 696

deger=0 0

deger=0 0

deger=0 0

deger=0 0

deger=0 12

deger=0 0

deger=0 0

BUILD STOPPED (total time: 44 seconds)

【问题讨论】:

  • 您是否为正在拆分的数据放置了 system.out.println("deger=" + deger) 以帮助确定问题所在?
  • 我提出并编辑了我的问题。如您所见,有时会有超过 2 个值。这是个问题,因为我的 split 函数只能得到两个值,而不是四个。
  • 无关:请学习java命名约定并遵守它们。
  • @D-Klotz,你对此有什么想法吗?
  • 最有可能的问题是您修改了 EDT 之外的数据集

标签: java multithreading swing jfreechart


【解决方案1】:

我找到了我必须删除此行的解决方案

  SES = obj;

因为它会覆盖我的SES 对象并导致数据混乱,还会导致会话锁定。

【讨论】:

  • 很好,您找到了 - 但这不是您的代码的唯一问题:您必须访问 EDT 上的所有 swing 属性(包括数据)。
  • 为什么我必须访问所有的 Swing 属性?
  • 不明白这个问题 - 您正在更改线程中的数据集,不是吗?或者是否记录了删除/添加方法允许任何线程使用? (他们可能在内部接管到 EDT 的切换,不知道;)
  • 在 JFreeChart 中,图表会在数据集值更改时自动更新。所以,这个解决方案现在有效。但我也必须研究 EDT。
  • 是的,我知道它们已更新 - 问题是谁负责保证 EDT 上的更新。我的赌注是客户端代码(与所有核心摇摆数据/模型相同)——不过,这是一个猜测。您最好尽快检查,因为 EDT 违规迟早会导致难以跟踪/调试的严重错误。祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多