OrderBook
类如下:
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
类和Client 2
类彼此不同(它们在其OrderBook
类上执行不同的写操作),并且它们是从不同的线程启动的。 Client
类如下:
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));
}
}
}
}
在Main
类中(在另一个线程中启动),当我尝试读取OrderBook
类正在修改的类Client x
的更新实例时,就会出现问题。 ..
Main
类看起来像这样...
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();
}
}
问题:
OrderBook
的两个实例的最新更新值?答案 0 :(得分:0)
您的资源应受锁保护。
您的同步块没有用,您应该保护OrderBook方法。
synchronized关键字用于保护资源。
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());
}
订单方法应该同步
public void synchronized updateBids(double bidPrice, double bidVol) {
// Edit critical data here
}
警告:构造一个将在线程之间共享的对象时,请非常小心,以免对该对象的引用过早“泄漏”。例如,假设您要维护一个名为instance的List,其中包含类的每个实例。您可能会想将以下行添加到构造函数中:instance.add(this); 但是然后其他线程可以使用实例访问对象,直到对象的构造完成。
您的OrderBook getter getLasValue正在泄漏