Bnojours,
Je m'essaie a JFreeChart et pour cela je crée un dashboard composé de 2 JfreeChart continuellement updaté mais selon des tempo differents. Pour cela J'utilise deux sets de variables totablement distinctes dans 2 Threads. Chaque thread fait appel à invokeLater dès qu'il s'agit de rafraichir les objets de la fenetre.
J'ai deux soucis :
a) Les threads démarrent dès l'appel de la fenetre, mais il continuent meme si la fenetre est fermée. Je voudrait bien qu'ils detectent au moins la fin de la fenetre. J'ai bien essayé avec un windows listener sur la fenetre mais elle est elle meme une fenetre derivée et la fonction events du listener me renvoie a la methode du super pas celle de cette fenetre.
b) J'ai des deadlock entre les threads et je ne parvient pas à comprendre pourquoi. Serait-ce l'object JDBC connection à Oracle qui serait l'origine du deadlock (il est unique mais est accéde en read only) ou bien l'appel a invokeLater ? J'utilise l'IDE JDeveloper et meme dans le thread monitor je ne parvient pas à determiner l'origine du deadlock.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 private void startGraph(){ // Thread to fill Redo generation size (mb) average per second thRedo = new Thread(new Runnable() { Integer lpos=0; Integer slp = Integer.parseInt((String)cbAutoApp.getItemAt(cbAutoAppLat.getSelectedIndex() )) *1000; String slp_S= (String)cbAutoApp.getItemAt(cbAutoAppLat.getSelectedIndex() ); String sqlRedo="select round(((value* "+GV.DB_BLOCK_SIZE[GV.getConectionIdx(conn)] + "/1048576))/"+ slp_S+",0) from v$sysstat where name ='redo blocks written'"; public void run() { System.out.println("Thread Started!"); while (true) { if (lpos ==AX_ROW){ for (int i=0 ; i<AX_ROW-1;i++) { arX[i]=arX[i+1]; arY[i]=arY[i+1]; } lpos=AX_ROW-1; } String var=GV.getTIME("hh:mi:ss"); if (lpos >0){ if (var.equalsIgnoreCase(arX[lpos-1]) ){ System.out.println("10) Continue called"); continue; //avoid duplicate entry in arX } } arX[lpos]=var; try { System.out.println("sql=" + sqlRedo); Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); String s_out=""; ResultSet rset; rset = stmt.executeQuery(sqlRedo); while (rset.next()) { s_out=rset.getString(1); } stmt.close(); arY[lpos] = Integer.parseInt(s_out); } catch (SQLException e) { System.out.println(e); } SwingUtilities.invokeLater(new Runnable(){ public void run() { chart.setNotify(false); // to avoid a repaint every time we modify the time serie dataset.removeSeries(s1); s1.clear(); int oldY=-1 ; for (int i=0;i<lpos;i++) { // first row must be skipped but its value is our basis reference if ( oldY == -1) { oldY=arY[i]; continue; } System.out.println("lpos="+ lpos +" i="+ i + " X=" + arX[i] + " oldY=" + oldY ) ; try { s1.addOrUpdate(new Second(df.parse(arX[i])), arY[i]-oldY ); } catch (ParseException e) { System.out.println(e); } oldY=arY[i]; } chart.setNotify(true); dataset.addSeries(s1); chart.fireChartChanged(); }}); // end InvokeLater slp = Integer.parseInt((String)cbAutoApp.getItemAt(cbAutoAppLat.getSelectedIndex() )) *1000; slp_S= (String)cbAutoApp.getItemAt(cbAutoAppLat.getSelectedIndex() ); sqlRedo="select round(((value* "+GV.DB_BLOCK_SIZE[GV.getConectionIdx(conn)] + "/1048576))/" + slp_S+",0) from v$sysstat where name ='redo blocks written'"; try { Thread.sleep(slp); } catch (InterruptedException e) { System.out.println(e); } lpos++; } // end while (true) } // end public void run }); // end Thread definition // Thread to fill Sreams Apply Latency (unit=seconds) average per second thLat = new Thread(new Runnable() { Integer lpos=0; Integer slp = Integer.parseInt((String)cbAutoAppLat.getItemAt(cbAutoAppLat.getSelectedIndex() )) *1000; String sqlLat="select round(nvl((ac.hwm_time - hwm_message_create_time)*86400, 0),0) " + " from v$streams_apply_coordinator ac, v$streams_apply_reader ar where ac.apply#=ar.apply# order by 1"; public void run() { System.out.println("Thread2 Started!"); while (true) { if (lpos ==AX_ROW){ for (int i=0 ; i<AX_ROW-1;i++) { latX[i]=latX[i+1]; latY[i]=latY[i+1];; } lpos=AX_ROW-1; } String var=GV.getTIME("hh:mi:ss"); if (lpos >0){ if (var.equalsIgnoreCase(latX[lpos-1]) ){ System.out.println("10) Continue called"); continue; //avoid duplicate entry in arX } } latX[lpos]=var; try { Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); String s_out=""; ResultSet rset; rset = stmt.executeQuery(sqlLat); while (rset.next()){ s_out=rset.getString(1); } stmt.close(); latY[lpos] = Integer.parseInt(s_out); latY[lpos]=latY[lpos]; } catch (SQLException e) { System.out.println(e); } SwingUtilities.invokeLater(new Runnable(){ public void run() { chartLat.setNotify(false); // to avoid a repaint every time we modify the time serie datasetLat.removeSeries(s2); s2.clear(); for (int i=0;i<lpos;i++) { try { s2.add(new Second(df2.parse(latX[i])), latY[i] ); } catch (ParseException e) { System.out.println(e); } } chartLat.setNotify(true); datasetLat.addSeries(s2); chartLat.fireChartChanged(); }}); // end invokeLater try { Thread.sleep( Integer.parseInt( (String)cbAutoAppLat.getItemAt(cbAutoAppLat.getSelectedIndex() ) ) *1000); } catch (InterruptedException e) { System.out.println(e); } if (cbAutoAppLat.equals(null)) break; lpos++; } // end while (true) } // end void run }); // end Thread 2 definition thRedo.start(); thLat.start(); }
Les objects graphiques sont definit et appele comme suit :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 // diagram for Redo size public class frame_dashboard extends abstract_frame1 implements ActionListener { private final int AX_ROW=11; // Max number of points private Connection conn; private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); private TimeSeriesCollection dataset = new TimeSeriesCollection(); private TimeSeriesCollection datasetLat= new TimeSeriesCollection(); private TimeSeries s1,s2; private JFreeChart chart, chartLat ; private Thread thRedo,thLat ; private JComboBox cbAutoApp, cbAutoAppLat ; private String arX [] = new String [AX_ROW]; // X label private int arY [] = new int [AX_ROW]; // Y values private int latY [] = new int [AX_ROW]; // Y values private String latX [] = new String [AX_ROW]; // Y values public frame_dashboard(Connection con) { conn=con; try { jbInit(); } catch (Exception e) { e.printStackTrace(); } } private void buildRedo(){ s1 = new TimeSeries("Redo",Second.class); //dataset.addSeries(s1); chart = ChartFactory.createTimeSeriesChart("System Activity", // Title "Time", // x-axis Label "Megabytes(s)", // y-axis Label dataset, // Dataset true, // Show Legend true, // Use tooltips false // Configure chart to generate URLs? ); ChartPanel cPanel = new ChartPanel(chart); chart.setRenderingHints( new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ) ); chart.setAntiAlias(true); XYPlot plot = (XYPlot) chart.getPlot(); plot.setRenderer( new XYSplineRenderer(1000) ); plot.setRangeGridlinesVisible(true); XYSplineRenderer renderer = (XYSplineRenderer) plot.getRenderer(); renderer.setSeriesPaint(0, Color.RED); // Redo renderer.setSeriesStroke( 0, new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL ) ); //renderer.setShapesVisible(false); renderer.setDrawOutlines(true); renderer.setUseFillPaint(true); JLabel jlSecs0 = new JLabel("Refresh Interval (s):"); jlSecs0.setBounds(new Rectangle(130,5, 140,20)); String [] secs = {"1","2","5","10", "30","60","300","900"} ; cbAutoApp = new JComboBox(secs); cbAutoApp.setBounds(260,5,50,25); cbAutoApp.setSelectedIndex(3); //cfAutoApp.addActionListener(this); this.getContentPane().add(cbAutoApp); cPanel.setBounds(new Rectangle(0,30, 1100,250) ); this.getContentPane().add(cPanel); this.getContentPane().add(jlSecs0); } // diagram for Latency apply private void buildLat(){ s2 = new TimeSeries("Apply Latency",Second.class); //dataset.addSeries(s1); chartLat = ChartFactory.createTimeSeriesChart("Apply Latency", // Title "Time", // x-axis Label "Time(s)", // y-axis Label datasetLat, // Dataset true, // Show Legend true, // Use tooltips false // Configure chart to generate URLs? ); ChartPanel cPanelLat = new ChartPanel(chartLat); chart.setRenderingHints( new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ) ); chart.setAntiAlias(true); XYPlot plot = (XYPlot) chart.getPlot(); plot.setRenderer( new XYSplineRenderer(1000) ); plot.setRangeGridlinesVisible(true); XYSplineRenderer renderer = (XYSplineRenderer) plot.getRenderer(); renderer.setSeriesPaint(0, Color.RED); renderer.setSeriesStroke( 0, new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL ) ); //renderer.setShapesVisible(false); renderer.setDrawOutlines(true); renderer.setUseFillPaint(true); JLabel jlSecs = new JLabel("Refresh tempo (s):"); jlSecs.setBounds(new Rectangle(130,280, 140,20)); String [] secs = {"1","2","5","10", "30","60","300","900"} ; cbAutoAppLat = new JComboBox(secs); cbAutoAppLat.setSelectedIndex(1); cbAutoAppLat.setBounds(260,280,50,25); JLabel lsecs = new JLabel("Refresh Interval(s) :"); lsecs.setBounds(new Rectangle(130, 280,140,20)); this.getContentPane().add(lsecs); cbAutoAppLat.addActionListener(this); this.getContentPane().add(cbAutoAppLat); cPanelLat.setBounds(new Rectangle(0,310, 1100,250) ); this.getContentPane().add(cPanelLat); } private void jbInit(){ setInstanceMenuBarColor(conn); set_title(" Streams Dashboard",0); this.setSize(new Dimension(1200, 900)); this.setLocation(10,10); /* graphic */ buildRedo(); buildLat(); startGraph(); setDefaultCloseOperation(DISPOSE_ON_CLOSE); }
Partager