Выполнение обратного вызова Java в потоке, выполняемом после запуска ()

Я использую библиотеку очереди заданий, где вы определяете Job и отправляете их в JobManager. У JobManager есть ThreadGroup с работниками, которые вытаскивают Job из очереди и вызывают Job.onRun().

Количество потоков задается путем указания максимального и минимального количества потоков, коэффициента загрузки (сколько незавершенных заданий может иметь рабочий поток перед созданием нового) и тайм-аута простоя для любого из потоков выше мин. Таким образом, run() рабочего потока завершится, если у него нет новых заданий и достигнут тайм-аут простоя.

В некоторых Job я использую библиотеки, которые предоставляют только асинхронный API. Безопасно ли использовать их в onRun()?

Например, если я хочу сделать сетевой запрос, который принимает обратный вызов, который дает мне ответ, будет ли вызван обратный вызов:

@Override
public void onRun() throws Throwable {
    client.doRequest(request, new Callback() {
        @Override
        public void onRequestComplete(Response response) {
            //is this guaranteed to get called?
        }
    });
    //since we now return from onRun() will onRequestComplete() get called?
}

person Eliezer    schedule 09.05.2014    source источник


Ответы (3)


Это безопасно, если вы знаете, что верно следующее (пока процесс жив):

  1. Метод onRun() каждого задания всегда будет выполняться (в конце концов), и
  2. Каждый используемый вами асинхронный API будет всегда вызывать свой метод обратного вызова (даже при наличии исключений).
person cybersam    schedule 09.05.2014
comment
Каждый onRun() в конечном итоге будет выполнен, и метод обратного вызова всегда вызывается (даже с исключениями). Процесс не привязан к этим потокам (существует отдельный основной поток). Можете ли вы объяснить, почему это безопасно? - person Eliezer; 10.05.2014
comment
Вы уверены, что у вас действительно несколько процессов? Каждый экземпляр виртуальной машины имеет один и только один процесс (который может иметь много потоков). В любом случае, если оба моих условия верны, то должно быть так, что в конечном итоге будет вызван каждый обратный вызов. Если, конечно, процесс, содержащий все потоки, не будет уничтожен (например, когда пользователь явно завершит процесс или компьютер отключится), но в этом случае ничто не может быть по-настоящему безопасным. - person cybersam; 10.05.2014
comment
Я немного сумбурно сформулировал свой ответ. Я хотел сказать, что все эти потоки находятся в одном процессе, и я спрашиваю только в контексте того, что процесс не умирает. - person Eliezer; 11.05.2014

Да, ваш обратный вызов будет выполняться до тех пор, пока процесс еще жив.

Если хотите, я создал программу для имитации именно этого. Он имеет три класса, просто поместите их в любой пакет и запустите, и вы увидите себя. Это показывает, что даже когда ваш рабочий поток завершает обратный вызов, он все равно приходит. Я надеюсь, что это помогает :)

Класс 1

public class Client {
    private static long startTime = System.currentTimeMillis();

    public static void main(String[] args) {
        System.out.println("Time elapsed in ms:" + (System.currentTimeMillis() - startTime));
        Client client = new Client();
        client.executeJob();
        try {
            System.out.println("Main thread sleeping");
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Main thread finishing");
    }

    public void executeJob() {
        new Thread() {
            @Override
            public void run() {
                Job job = new Job();
                System.out.println("Calling Job with Asyc - Time elapsed in ms:" 
                        + (System.currentTimeMillis() - startTime));
                job.doRequest("Calling Async", new CallBack() {

                    @Override
                    public void onRequestComplete(String response) {
                        System.out.println("Got my callback eventhough job that started the Async is over - Time elapsed in ms:" 
                                + (System.currentTimeMillis() - startTime));
                    }
                });
                System.out.println("Job thread finishing");
            }
        }.start();
    }
}

Класс 2

public abstract class CallBack {
    public abstract void onRequestComplete(String response);
}

Класс 3

public class Job {
    public void doRequest(String request, final CallBack callBack){
        new Thread() {
            @Override
            public void run() {
                //Async Long running task
                try {
                    Thread.sleep(10000);
                    callBack.onRequestComplete("Long Async task Completed-- Sending response back");
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }.start();
    }
}
person vkg    schedule 09.05.2014

Да и Нет

ДА: вы предоставляете экземпляр Callback объекту client. Клиент просто вызовет метод onRequestComplete после получения ответа (от сервера).

НЕТ: если больше нет запущенных потоков и есть невыполненные запросы, они могут быть отменены, так как приложение будет остановлено.

Но я думаю, вы спрашивали о нормальном выполнении, а не об отключении JVM.

Итак, я предполагаю, что ДА, но я не знаю реализацию клиента (я предполагаю, что он запускает поток, внутри которого есть какой-то механизм событий).

person Christian Kuetbach    schedule 09.05.2014
comment
Процесс не привязан к этим потокам (существует отдельный основной поток). Можете ли вы объяснить, почему это безопасно? - person Eliezer; 10.05.2014