Subversion Repositories Integrator Subversion

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
771 blopes 1
/*
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
3
 *  contributor license agreements.  See the NOTICE file distributed with
4
 *  this work for additional information regarding copyright ownership.
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
6
 *  (the "License"); you may not use this file except in compliance with
7
 *  the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 *  Unless required by applicable law or agreed to in writing, software
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 *  See the License for the specific language governing permissions and
15
 *  limitations under the License.
16
 */
17
package async;
18
 
19
import java.text.DecimalFormat;
20
import java.util.List;
21
import java.util.Random;
22
import java.util.concurrent.CopyOnWriteArrayList;
23
import java.util.concurrent.atomic.AtomicInteger;
24
 
25
public class Stockticker implements Runnable {
26
        public volatile boolean run = true;
27
        protected final AtomicInteger counter = new AtomicInteger(0);
28
        final List<TickListener> listeners = new CopyOnWriteArrayList<>();
29
        protected volatile Thread ticker = null;
30
        protected volatile int ticknr = 0;
31
 
32
        public synchronized void start() {
33
            run = true;
34
            ticker = new Thread(this);
35
            ticker.setName("Ticker Thread");
36
            ticker.start();
37
        }
38
 
39
        public synchronized void stop() {
40
            // On context stop this can be called multiple times.
41
            // NO-OP if the ticker thread is not set
42
            // (i.e. stop() has already completed)
43
            if (ticker == null) {
44
                return;
45
            }
46
            run = false;
47
            try {
48
                ticker.join();
49
            }catch (InterruptedException x) {
50
                Thread.interrupted();
51
            }
52
 
53
            ticker = null;
54
        }
55
 
56
        public void shutdown() {
57
            // Notify each listener of the shutdown. This enables them to
58
            // trigger any necessary clean-up.
59
            for (TickListener l : listeners) {
60
                l.shutdown();
61
            }
62
            // Wait for the thread to stop. This prevents warnings in the logs
63
            // that the thread is still active when the context stops.
64
            stop();
65
        }
66
 
67
        public void addTickListener(TickListener listener) {
68
            if (listeners.add(listener)) {
69
                if (counter.incrementAndGet()==1) {
70
                    start();
71
                }
72
            }
73
 
74
        }
75
 
76
        public void removeTickListener(TickListener listener) {
77
            if (listeners.remove(listener)) {
78
                if (counter.decrementAndGet()==0) {
79
                    stop();
80
                }
81
            }
82
        }
83
 
84
        @Override
85
        public void run() {
86
            try {
87
 
88
                Stock[] stocks = new Stock[] { new Stock("GOOG", 435.43),
89
                        new Stock("YHOO", 27.88), new Stock("ASF", 1015.55), };
90
                Random r = new Random(System.currentTimeMillis());
91
                while (run) {
92
                    for (int j = 0; j < 1; j++) {
93
                        int i = r.nextInt() % 3;
94
                        if (i < 0) {
95
                            i = i * (-1);
96
                        }
97
                        Stock stock = stocks[i];
98
                        double change = r.nextDouble();
99
                        boolean plus = r.nextBoolean();
100
                        if (plus) {
101
                            stock.setValue(stock.getValue() + change);
102
                        } else {
103
                            stock.setValue(stock.getValue() - change);
104
                        }
105
                        stock.setCnt(++ticknr);
106
                        for (TickListener l : listeners) {
107
                            l.tick(stock);
108
                        }
109
 
110
                    }
111
                    Thread.sleep(850);
112
                }
113
            } catch (InterruptedException ix) {
114
                // Ignore
115
            } catch (Exception x) {
116
                x.printStackTrace();
117
            }
118
        }
119
 
120
 
121
    public interface TickListener {
122
        void tick(Stock stock);
123
        void shutdown();
124
    }
125
 
126
    public static final class Stock implements Cloneable {
127
        protected static final DecimalFormat df = new DecimalFormat("0.00");
128
        protected final String symbol;
129
        protected double value = 0.0d;
130
        protected double lastchange = 0.0d;
131
        protected int cnt = 0;
132
 
133
        public Stock(String symbol, double initvalue) {
134
            this.symbol = symbol;
135
            this.value = initvalue;
136
        }
137
 
138
        public void setCnt(int c) {
139
            this.cnt = c;
140
        }
141
 
142
        public int getCnt() {
143
            return cnt;
144
        }
145
 
146
        public String getSymbol() {
147
            return symbol;
148
        }
149
 
150
        public double getValue() {
151
            return value;
152
        }
153
 
154
        public void setValue(double value) {
155
            double old = this.value;
156
            this.value = value;
157
            this.lastchange = value - old;
158
        }
159
 
160
        public String getValueAsString() {
161
            return df.format(value);
162
        }
163
 
164
        public double getLastChange() {
165
            return this.lastchange;
166
        }
167
 
168
        public void setLastChange(double lastchange) {
169
            this.lastchange = lastchange;
170
        }
171
 
172
        public String getLastChangeAsString() {
173
            return df.format(lastchange);
174
        }
175
 
176
        @Override
177
        public int hashCode() {
178
            return symbol.hashCode();
179
        }
180
 
181
        @Override
182
        public boolean equals(Object other) {
183
            if (other instanceof Stock) {
184
                return this.symbol.equals(((Stock) other).symbol);
185
            }
186
 
187
            return false;
188
        }
189
 
190
        @Override
191
        public String toString() {
192
            StringBuilder buf = new StringBuilder("STOCK#");
193
            buf.append(getSymbol());
194
            buf.append('#');
195
            buf.append(getValueAsString());
196
            buf.append('#');
197
            buf.append(getLastChangeAsString());
198
            buf.append('#');
199
            buf.append(String.valueOf(getCnt()));
200
            return buf.toString();
201
 
202
        }
203
 
204
        @Override
205
        public Object clone() {
206
            Stock s = new Stock(this.getSymbol(), this.getValue());
207
            s.setLastChange(this.getLastChange());
208
            s.setCnt(this.cnt);
209
            return s;
210
        }
211
    }
212
}