Как многократные (неопределенные) асинхронные обратные вызовы.есть шаблон дизайна или что-то еще? - PullRequest
0 голосов
/ 23 сентября 2019

Я не уверен, правильно ли я спросил в заголовке, но здесь проблема.У меня есть класс, который делает Jop асинхронно, а также должен работать в потоке пользовательского интерфейса Swing.вот так


SwingUtilities.invokeLater(() -> {
  myobj.dosomething(()->{

   SwingUtilities.invokeLater(() -> {
     myobj.dosomething(()->{
       //here it needs to repeat this again and again. 
       //for an indefinte number of times. So it is hedious to reapat this code
       //for few times  and impossible to make it dynamic based on user input. 
       //it was even worse without lambda sytax.
     });
    });
   });
});

Редактировать: Наверное, мне вообще не стоило упоминать свинг.Потому что это не проблема, это только добавляет к этому.Основная проблема в том, что мне нужно звонить myobj.dosomething(()->{ слишком много раз.И каждый раз, когда это должно начаться после того, как предыдущий звонок сделан.

Ответы [ 2 ]

0 голосов
/ 24 сентября 2019

Используя семафор, вы можете запускать асинхронные задачи по порядку.В следующем примере планируются действия с использованием пула потоков:

public class SemaphoreSample {

    static class MyObject {
        private final int waitTime;
        private final String name;

        MyObject(int waitTime, String name) {
            this.waitTime = waitTime;
            this.name = name;
        }

        void doSomething(Semaphore s) {
            try {
                s.acquire();
                TimeUnit.SECONDS.sleep(waitTime);
                System.out.println(String.format("%s did something after %ds", name, waitTime));
                s.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        Random rd = new Random();
        boolean firstInFirstOutOrder = true;
        Semaphore s = new Semaphore(1, firstInFirstOutOrder);

        for (int i = 0; i < 10; i++) {
            MyObject o = new MyObject(rd.nextInt(4), String.format("#%d", i));

            threadPool.submit(() -> o.doSomething(s));
        }
        threadPool.shutdown();
    }
}

Когда предполагается выполнение асинхронного действия, он сначала проверяет семафор на наличие доступного разрешения.Если оно доступно, действие выполняется немедленно.В противном случае он ожидает завершения других действий.Семафор гарантирует порядок «первым пришел - первым вышел» для запланированных действий.

Вывод для приведенного выше примера выглядит следующим образом:

#0 did something after 1s
#1 did something after 0s
#2 did something after 0s
#3 did something after 0s
#4 did something after 3s
#5 did something after 1s
#6 did something after 3s
#7 did something after 0s
#8 did something after 1s
#9 did something after 2s

РЕДАКТИРОВАТЬ : Обычно это не такразрешено блокировать поток пользовательского интерфейса, поэтому s.acquire() не должен вызываться потоком пользовательского интерфейса.Вместо этого вы можете сделать что-то вроде:

void scheduleUiUpdate(Runnable r) {
    threadPool.submit(() -> {
        try {
            semaphore.acquire();
            SwingUtilities.invokeAndWait(r);
            semaphore.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}

Обратите внимание, что порядок FIFO гарантируется при вызове конструктора семафора с флагом fair , установленным как true .

0 голосов
/ 24 сентября 2019

Если вы не хотите использовать свинг-таймеры, создайте поток и отправьте свой код пользовательского интерфейса обратно в поток пользовательского интерфейса следующим образом:

Runnable r = new Runnable() {

    public void run() {

         while (condition holds) {
            //sleep, do work, etc.

            //Post UI code back to the Swing thread
            SwingUtilities.invokeLater(() -> { //some ui code }
         }
    }
};

Thread t = new Thread(r);
t.start();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...