This scheme shows the functions that are being discussed below...
The OrderBook
class looks like this:
public class OrderBook {
private TreeMap<Double, Double> bids;
private TreeMap<Double, Double> asks;
private Entry<Double, Double> bestBid;
private Entry<Double, Double> bestAsk;
public OrderBook() {
this.bids = new TreeMap<>();
this.asks = new TreeMap<>();
}
// Getters and setters...
// Example function that modifies its variables...
public void updateBids(double bidPrice, double bidVol) {
if(this.getBids().containsKey(bidPrice)) {
if(bidVol == 0.0) {
//System.out.println("Vol. 0: " + bidPrice + " - " + bidVol);
this.getBids().remove(bidPrice);
}
else if(bidVol > 0.0) {
//System.out.println("Actualizar Vol.: " + bidPrice + " - " + bidVol);
this.getBids().replace(bidPrice, bidVol);
}
else {
//System.out.println("Error. Unexpected volume:" +
// bidPrice + " - " + vol);
}
}
else {
// ...
}
this.setBestBid(this.getBids().lastEntry());
}
}
Client 1
class and Client 2
class are different from each other (they perform different write operations over the their OrderBook
class) and they are launched from different threads. A Client
class looks like this:
public class Client1 extends WebSocketClient {
private OrderBook ob;
public Client1(URI serverURI, OrderBook ob) {
super(serverURI);
this.ob = ob;
}
// Extended class implementations...
@Override
public void onMessage(String message) {
parse(message);
}
private void parse(String msg) {
JSONObject json = new JSONObject(msg);
if(json.has("b")) {
double b = json.getDouble("b");
double a = json.getDouble("a");
double B = json.getDouble("B");
double A = json.getDouble("A");
/**
* HERE performs the modification of the OrderBook class passed in the
* constructor. I don't know if this synchronized block is needed...
*/
synchronized(this.ob) {
this.ob.setBestBid(new AbstractMap.SimpleEntry<>(bidPrice, bidVol));
this.ob.setBestAsk(new AbstractMap.SimpleEntry<>(askPrice, askVol));
}
}
}
}
The problem comes when in the Main
class (launched in another thread), I try to read the updated instances of the class OrderBook
that are being modified by the Client x
classes...
Main
class looks like this...
public class Main implements Runnable {
private OrderBook ob1;
private OrderBook ob2;
public Oportunity(OrderBook ob1, OrderBook ob2) throws URISyntaxException {
this.ob1 = ob1;
this.ob2 = ob2;
}
@Override
public void run() {
while(true) {
// PROBLEM HERE: doesn't show anything...
System.out.println(this.ob1.getLasValue());
System.out.println(this.ob2.getLasValue());
}
}
public static void main(String[] args) throws Throwable {
OrderBook ob1 = new OrderBook();
OrderBook ob2 = new OrderBook();
Thread client1 = new Thread(new Client1(new URI("..."), ob1));
Thread client2 = new Thread(new Client2(new URI("..."), ob2));
Thread m = new Thread(new Main(ob1, ob2));
client1.start();
client2.start();
m.start();
}
}
QUESTIONS:
OrderBook
?Your resource should be protected by a Lock.
Your synchronized block is useless, you should protect OrderBook methods.
synchronized keyword is used to protect resources.
public class CriticalData {
private int sum = 0;
public void synchronized add() {
this.setSum(this.getSum() + 1);
}
// Synchronized Getters & setters
}
@Test
public void multiThreadedAddition() {
// GIVEN
ExecutorService service = Executors.newFixedThreadPool(3);
CriticalData data = new CriticalData();
// WHEN
IntStream.range(0, 1000)
.forEach(count -> service.submit(data::add));
service.awaitTermination(1000, TimeUnit.MILLISECONDS);
// THEN
assertEquals(1000, data.getSum());
}
Orderbook methods should be synchronized
public void synchronized updateBids(double bidPrice, double bidVol) {
// Edit critical data here
}
Warning: When constructing an object that will be shared between threads, be very careful that a reference to the object does not "leak" prematurely. For example, suppose you want to maintain a List called instances containing every instance of class. You might be tempted to add the following line to your constructor: instances.add(this); But then other threads can use instances to access the object before construction of the object is complete.
Your OrderBook getter getLasValue is leaking
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.