В телеграмм боте запуск бота в несколько потоков

108
23 августа 2019, 05:10

Всем привет! Сделал телеграм бота, который, в ответ на запрос "название города", отправляет данные о погоде на сегодня и завтра. Всё работает, теперь надо сделать, чтобы он работал в несколько потоков, чтобы не создавать очередь в случае, когда несколько пользователей одновременно отправляют запрос на погоду.

Код бота такой

public class Bot extends TelegramLongPollingBot {
    private static final String NAME_OF_BOT = "MyWeather129Bot";
    private static final String BOT_TOKEN = "657869679:AAGZ5xy_V5WyTDWy7Ex8HorP-UABJKT****";
    public SqlMethods source;
    public void onUpdateReceived(Update update){
        Message message = update.getMessage();
if(message.getText().equals("/start")){
            sendMSG(message, "Привет, "+ message.getChat().getFirstName()+"!"+ System.lineSeparator()+
                    "Для просмотра погоды нужно выбрать место нахождения." +
                    System.lineSeparator()+
                    "Для этого достаточно написать название населенного пункта и страну в чат" +
                    "(Например Sankt-Peterburg или Санкт-Петербург)");
        }
        else if(message != null && message.hasText() && !message.getText().equals("/start")) {
            try {
                sendMSG(message, Weather.getWeather(message.getText()));
                sendMSG(message, WeatherTomorrow.getWeatherTomorrow(message.getText()));
            } catch (IOException e) {
                sendMSG(message, "Город не найден!напишите название населенного пункта в чат " +
                        "(Например Sankt-Peterburg или Санкт-Петербург)");
            }
        }
        else if (message.getText().equals("/subscribe")) {
            sendMSG(message, "Напишите название населённого пункта," +
                    "для которого вы хотите получать ежедневный прогноз погоды");
            long id = message.getChatId();
            String userName = message.getChat().getUserName();
            String firstName = message.getChat().getFirstName();
            String location = message.getText();
            boolean subResult = source.addSubscriber(id, userName, firstName);
            if (subResult) {
                sendMSG(message, "Спасибо за подписку :)");
            } else {
                sendMSG(message, "Не удалось подписаться!");
            }
        }
         else if (message.getText().equals("/unsubscribe")){
            long deleteId = message.getChatId();
            boolean unsubResult = source.deleteSubscriber(deleteId);
            if(unsubResult){
                sendMSG(message, "Вы отписались от прогноза погоды :(");
            } else{
                sendMSG(message, "Не удалось отписаться!");
            }
        }
        else {
            sendMSG(message, "напишите название населенного пункта в чат " +
                    "(Например Sankt-Peterburg или Санкт-Петербург)");
        }
    }
    public void sendMSG(Message message, String text){
        SendMessage sendMessage = new SendMessage();
        sendMessage.enableMarkdown(true);
        sendMessage.setChatId(message.getChatId().toString());
        sendMessage.setReplyToMessageId(message.getMessageId());
        sendMessage.setText(text);
        try {
            execute(sendMessage);
            setButtons(sendMessage);
        }catch (TelegramApiException e){
            e.printStackTrace();
        }
    }
    public void setButtons(SendMessage sendMessage){
        ReplyKeyboardMarkup replyKeyboardMarkup = new ReplyKeyboardMarkup();
        sendMessage.setReplyMarkup(replyKeyboardMarkup);
        replyKeyboardMarkup.setSelective(true);
        replyKeyboardMarkup.setOneTimeKeyboard(false);
        replyKeyboardMarkup.setOneTimeKeyboard(false);

        List<KeyboardRow> keyboardRowList = new ArrayList<>();
        KeyboardRow keyboardFirstRow = new KeyboardRow();
        keyboardRowList.add(keyboardFirstRow);
        replyKeyboardMarkup.setKeyboard(keyboardRowList);
    }
    public String getBotUsername(){
        return NAME_OF_BOT;
    }
    public String getBotToken(){
        return BOT_TOKEN;
    }
}

Класс Weather

public class Weather {

    public static final String URL_SOURCE = "http://api.openweathermap.org/data/2.5/weather?q=";
    public static final String API_KEY = "&APPID=3ad54740fd37f3f14a3a32a09f09cd25";
    public static final String UNITS = "&units=metric";
    public static final String LANG = "&lang=ru";

    public static String getWeather(String message) throws IOException{
        // get weather data from URL
        URL url = new URL(URL_SOURCE + message + LANG + UNITS + API_KEY);
        InputStreamReader reader = new InputStreamReader(url.openStream());
        OneDayWeather todayWeatherData = null;
        Gson todayWeatherGson = new Gson();
        todayWeatherData = todayWeatherGson.fromJson(reader, OneDayWeather.class);
        System.out.println("В городе " + todayWeatherData.getName() + " сегодня "+ System.lineSeparator() +
                "Температура: " + String.format("%.1f", todayWeatherData.getTemp().getTemp()) + "°C, " + System.lineSeparator()+
                "Влажность: " + todayWeatherData.getTemp().getHumidity() + "%, " + System.lineSeparator()+
                "Осадки: " + todayWeatherData.getWeatherToday().get(0).getDescription()+ System.lineSeparator()+
                "Скорость ветра: " + (int)todayWeatherData.getWind().getSpeed() + " м/с" + System.lineSeparator()+
                "http://openweathermap.org/img/w/" + todayWeatherData.getWeatherToday().get(0).getIcon() + ".png");

        return "В городе: " + todayWeatherData.getName() + " сегодня "+ System.lineSeparator() +
                "Температура: " + String.format("%.1f", todayWeatherData.getTemp().getTemp()) + "°C, " + System.lineSeparator()+
                "Влажность: " + todayWeatherData.getTemp().getHumidity() + "%, " + System.lineSeparator()+
                "Осадки: " + todayWeatherData.getWeatherToday().get(0).getDescription() + System.lineSeparator()+
                "Скорость ветра: " + (int)todayWeatherData.getWind().getSpeed() + " м/с" + System.lineSeparator()+
                "http://openweathermap.org/img/w/" + todayWeatherData.getWeatherToday().get(0).getIcon() + ".png";
    }
}

Как я понял, необходимо сделать, чтобы в классе Weather запросы к серверу погоды шли в отдельном потоке. Вот цитата из задания к боту: "Стоит заметить, что обращения к OpenWeatherMap должны происходить в отдельном потоке". У меня своими силами реализовать не получается.

Answer 1

вот такая замена выполнит запрос в другом потоке (лучше использовать специально предназначенные для этого конструкции):
скорее всего, запрос на сайт отправляется в этой строке:

todayWeatherData = todayWeatherGson.fromJson(reader, OneDayWeather.class);

заменить ее на:

//todayWeatherData уже объявлена
Thread th = new Thread(
  ()->{
    todayWeatherData = todayWeatherGson.fromJson(reader, OneDayWeather.class);
  }
);
//запуск потока
th.Start();
//ожидание его завершения (текущий поток засыпает до окончания th)
th.Join();

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

READ ALSO
WildFly + Drools = GC overhead limit exceeded

WildFly + Drools = GC overhead limit exceeded

Есть такая штука как "Друлз": у него есть веб-приложение, позволяющее писать бизнес-правила прямо в браузере - называется "Business Central Workbench"

103
Как передать объект в RequestBody?

Как передать объект в RequestBody?

В форме ввожу данные(строка и столбец) и нажимаю на сабмит

117
Синхронизация группы объектов

Синхронизация группы объектов

Доброго времени суток

113