Blame |
Last modification |
View Log
| Download
| RSS feed
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package async;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public class Stockticker
implements Runnable {
public volatile boolean run =
true;
protected final AtomicInteger counter =
new AtomicInteger(0);
final List<TickListener
> listeners =
new CopyOnWriteArrayList<>();
protected volatile Thread ticker =
null;
protected volatile int ticknr =
0;
public synchronized void start
() {
run =
true;
ticker =
new Thread(this);
ticker.
setName("Ticker Thread");
ticker.
start();
}
public synchronized void stop
() {
// On context stop this can be called multiple times.
// NO-OP if the ticker thread is not set
// (i.e. stop() has already completed)
if (ticker ==
null) {
return;
}
run =
false;
try {
ticker.
join();
}catch (InterruptedException x
) {
Thread.
interrupted();
}
ticker =
null;
}
public void shutdown
() {
// Notify each listener of the shutdown. This enables them to
// trigger any necessary clean-up.
for (TickListener l : listeners
) {
l.
shutdown();
}
// Wait for the thread to stop. This prevents warnings in the logs
// that the thread is still active when the context stops.
stop
();
}
public void addTickListener
(TickListener listener
) {
if (listeners.
add(listener
)) {
if (counter.
incrementAndGet()==
1) {
start
();
}
}
}
public void removeTickListener
(TickListener listener
) {
if (listeners.
remove(listener
)) {
if (counter.
decrementAndGet()==
0) {
stop
();
}
}
}
@
Override
public void run
() {
try {
Stock
[] stocks =
new Stock
[] { new Stock
("GOOG",
435.43),
new Stock
("YHOO",
27.88),
new Stock
("ASF",
1015.55),
};
Random r =
new Random(System.
currentTimeMillis());
while (run
) {
for (int j =
0; j
< 1; j++
) {
int i = r.
nextInt() % 3;
if (i
< 0) {
i = i
* (-
1);
}
Stock stock = stocks
[i
];
double change = r.
nextDouble();
boolean plus = r.
nextBoolean();
if (plus
) {
stock.
setValue(stock.
getValue() + change
);
} else {
stock.
setValue(stock.
getValue() - change
);
}
stock.
setCnt(++ticknr
);
for (TickListener l : listeners
) {
l.
tick(stock
);
}
}
Thread.
sleep(850);
}
} catch (InterruptedException ix
) {
// Ignore
} catch (Exception x
) {
x.
printStackTrace();
}
}
public interface TickListener
{
void tick
(Stock stock
);
void shutdown
();
}
public static final class Stock
implements Cloneable {
protected static final DecimalFormat df =
new DecimalFormat("0.00");
protected final String symbol
;
protected double value = 0.0d
;
protected double lastchange = 0.0d
;
protected int cnt =
0;
public Stock
(String symbol,
double initvalue
) {
this.
symbol = symbol
;
this.
value = initvalue
;
}
public void setCnt
(int c
) {
this.
cnt = c
;
}
public int getCnt
() {
return cnt
;
}
public String getSymbol
() {
return symbol
;
}
public double getValue
() {
return value
;
}
public void setValue
(double value
) {
double old =
this.
value;
this.
value = value
;
this.
lastchange = value - old
;
}
public String getValueAsString
() {
return df.
format(value
);
}
public double getLastChange
() {
return this.
lastchange;
}
public void setLastChange
(double lastchange
) {
this.
lastchange = lastchange
;
}
public String getLastChangeAsString
() {
return df.
format(lastchange
);
}
@
Override
public int hashCode
() {
return symbol.
hashCode();
}
@
Override
public boolean equals
(Object other
) {
if (other
instanceof Stock
) {
return this.
symbol.
equals(((Stock
) other
).
symbol);
}
return false;
}
@
Override
public String toString
() {
StringBuilder buf =
new StringBuilder("STOCK#");
buf.
append(getSymbol
());
buf.
append('#');
buf.
append(getValueAsString
());
buf.
append('#');
buf.
append(getLastChangeAsString
());
buf.
append('#');
buf.
append(String.
valueOf(getCnt
()));
return buf.
toString();
}
@
Override
public Object clone
() {
Stock s =
new Stock
(this.
getSymbol(),
this.
getValue());
s.
setLastChange(this.
getLastChange());
s.
setCnt(this.
cnt);
return s
;
}
}
}