Помощь в архитектуре

Я создаю программу для одновременной торговли с разных бирж.

Выгладит примерно таким образом, я создаю потоки, каждый хранит апи ключ и криптобиржу(binance, hitbtc, exmo), после они выполняю метод run():

@Override
public void run(){
   while(true){
     if(условие) placeOrder();
     if(условие) cancelOrder();
   }
}

И вот когда они выполняю методы placeOrder или cancelOrder реализация сильно меняется взависимости от криптобиржи, выглядит примерно так:

synchronized void placeOrder(){
   String link = ""; // это может быть api.hitbtc.com или api.binance.com...
   String method = "POST";
   Url url = new Url(link);
   HttpURLConnection con = (HttpURLConnection) url.openConnection();
   con.setRequestMethod(method);
}

И нужно чтобы для каждой биржи ставился правильный url но если использовать if, то их выйдет много и это замедлит программу.


Ответы (1 шт):

Автор решения: Alexey R.

Вам не следует вычислять адрес эндпоинта внутри потока. Этот адрес врядли будет меняться, поэтому лучше сделать этот адрес неотъемлемым свойством самого потока на этапе его создания.

Способ 1: Сделайте в Вашем классе абстрактный метод, возвращающий урл. Например так:

public abstract class Trader implements Runnable{

    @Override
    public void run() {
        // ...
        placeOrder();
        // ...
    }

    private void placeOrder(){
        String link = getApiEndpoint();
        // ...
    }

    abstract String getApiEndpoint();

}

И при заполнении пула тредами, переопределяйте его вот так:

public class Bot {

    public static void main(String[] args) {
        ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(2);
        threadPoolExecutor.execute(
                new Trader() {
                    @Override
                    String getApiEndpoint() {
                        return "binance-api";
                    }
                });
        threadPoolExecutor.execute(
                new Trader() {
                    @Override
                    String getApiEndpoint() {
                        return "exmo-api";
                    }
                });
    }

}

Способ 2: просто передавайте нужное значение через конструктор:

public class Trader implements Runnable{

    String apiEndpoint;
    
    public Trader(String apiEndpoint){
        this.apiEndpoint = apiEndpoint;
    }
    
    @Override
    public void run() {
        // ...
        placeOrder();
        // ...
    }

    private void placeOrder(){
        // Use apiEndpoint here;
    }

}

И затем:

public class Bot {

    public static void main(String[] args) {
        ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(2);
        threadPoolExecutor.execute(new Trader("binance-api"));
        threadPoolExecutor.execute(new Trader("exmo-api"));
    }

}

P.S. - В первом случае Вы сможете использовать механизм обратного вызова если потребуется, т.е. обращаться к коду вызывающего потока из вызываемого.

→ Ссылка