我向客户发送价格(10000+)但是代码下面有循环导致客户等待计算的过程延迟。
PriceVisibleForCustomer =价格+ CustomerMargin
价格 - 每隔300毫秒更换一次 - 从中央商店发送,与客户实例无关
CustomerMargn - 由客户协议/分部/管理员决定等产生的一些正负金额。在客户http会话期间没有变化,我可以将其保留在内存中
客户 - 他登录后参与了这个过程,他应该看到8种产品价格的快速变化。
也许我需要更多技术?我有Spring 3/4,Java,Weblogic,我可以为此任务创建甚至单独的webapp来提供计算价格。
我考虑过Java中的线程,但是10000多个客户意味着太多的线程不是吗?如何更改此代码?也许我应该改变架构,但是如何?
/**
* Sends prices to customer. This method is called very often (300ms) as prices are changing in real time.
* Customer should see prices also each 300ms
* @param productId - id of a product that prices will be calculated
* @param productIdToPriceMap
* @param customerIdToMarginMap - this map is changed every time customer logs in or logs out
*/
private static void sendPricesToCustomers(Long productId,
Map<Long, BigDecimal> productIdToPriceMap,
Map<Long, BigDecimal> customerIdToMarginMap) {
//This loop is blocking last customer from receiving price until all other customers wil have theri prices calculated. I could create threads, 10000+ customers will be logged in, I cant create so much threads... can I?
for (Long customerId: customerIdToMarginMap.keySet()){
BigDecimal customerMargin = customerIdToMarginMap.get(customerId);
BigDecimal priceResult = productIdToPriceMap.get(productId).add(customerMargin);
//send priceResult to websocket
}
}
答案 0 :(得分:1)
这是一个监听器模式的简单示例,我不确定这种方法是否适合您,但只是抛出一些想法......
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.Timer;
public class Demo {
public static Product[] PRODUCTS = new Product[]{
new Product("Computer", 400),
new Product("Desk", 800),
new Product("Chair", 70),
new Product("Printer", 300),
new Product("Television", 200)
};
public static void main(String[] args) throws InterruptedException {
Customer john = new Customer("John", 3);
john.addProduct(PRODUCTS[1]);
john.addProduct(PRODUCTS[2]);
john.addProduct(PRODUCTS[3]);
Customer mary = new Customer("Mary", 2);
mary.addProduct(PRODUCTS[1]);
mary.addProduct(PRODUCTS[2]);
mary.addProduct(PRODUCTS[4]);
Thread.sleep(10000);
System.exit(0);
}
}
interface IPriceListener {
public void priceChanged(Product product, int price);
}
class Customer implements IPriceListener {
String _name;
int _margin;
Vector<Product> _products = new Vector<Product>();
public Customer(String name, int margin){
_name = name;
_margin = margin;
}
public void addProduct(Product product){
_products.add(product);
product.addListener(this);
}
public void priceChanged(Product product, int price) {
System.out.println("[" + _name + "][" + _products.get(_products.indexOf(product)).getName() + "][" + price + "][" + (price + _margin) + "]");
}
}
class Product implements ActionListener {
private int _startingPrice;
private int _currentPrice;
private String _name;
private Timer _timer;
private Vector<IPriceListener> _listeners = new Vector<IPriceListener>();
public Product(String name, int price) {
_name = name;
_startingPrice = _currentPrice = price;
_timer = new Timer(300, this);
_timer.start();
}
public void addListener(IPriceListener listener) {
_listeners.add(listener);
}
public void removeListener(IPriceListener listener){
_listeners.remove(listener);
}
private void notifyListeners() {
for(IPriceListener listener : _listeners){
listener.priceChanged(this, getCurrentPrice());
}
}
public void actionPerformed(ActionEvent e) {
_currentPrice = _startingPrice + (int)(Math.random() * (5 - (-5))) + (-5);
notifyListeners();
}
public final String getName() {
return _name;
}
private synchronized final int getCurrentPrice() {
return _currentPrice;
}
}
答案 1 :(得分:0)
解决这个问题的一种方法是创建一个单独的线程,其作用是从队列中消耗priceResults并将它们发送到websocket(我假设你只有一个websocket)。然后,您的循环将每300毫秒将priceResults推送到队列,而不会阻止websocket线程。请参阅ConcurrentLinkedQueue javadoc。
修改强>
为了避免在完成当前循环到_JAVA_OPTION
之间的延迟并开始循环下一次更新,这里有一些选项:
保持队列概念并创建一个固定的线程池,其中每个线程从队列中提取下一个customerIdToMarginMap
/ customerId
/ productIdToPriceMap
。如果您有四个线程和10,000个记录,则每个线程只需处理2,500条记录,从而比当前实现早4次开始下一次300ms数据。在您发现性能所需的时候增加线程数。
保留原始队列概念,但更改收到价格更新的方式。您需要循环的原因是因为您同时获得每个客户的定价更新。如果你可以改为为一组客户创建一个线程监听器,这些客户收到的customerIdToMarginMap
只包含它要处理的customerIdToMarginMap
,迭代时间将会大大减少。