Java - ThreadPool ждет завершения задачи [дубликат]

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

 document.addEventListener('click',function(e){
    if(e.target && e.target.id== 'brnPrepend'){//do something}
 })

jquery упростить:

 $(document).on('click','#btnPrepend',function(){//do something})

Вот статья, которую вы можете прочитать о делеции делегирования событий .

66
задан Neeta 5 February 2012 в 14:09
поделиться

8 ответов

Использование Future, описанное в приведенных выше ответах, выполняет задание, но немного менее существенно, как f.get (), блокирует поток до получения результата, что нарушает параллелизм.

Лучшее решение - использовать ListenableFuture от Guava. Пример:

    ListenableFuture<Void> future = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1, new NamedThreadFactory).submit(new Callable<Void>()
    {
        @Override
        public Void call() throws Exception
        {
            someBackgroundTask();
        }
    });
    Futures.addCallback(future, new FutureCallback<Long>()
    {
        @Override
        public void onSuccess(Long result)
        {
            doSomething();
        }

        @Override
        public void onFailure(Throwable t)
        {

        }
    };
1
ответ дан bitsabhi 17 August 2018 в 21:50
поделиться

Как насчет этого решения?

Он не использует класс Thread, но он является параллельным и таким образом делает именно то, что вы запрашиваете

ExecutorService pool = Executors.newFixedThreadPool(2); // creates a pool of threads for the Future to draw from

Future<Integer> value = pool.submit(new Callable<Integer>() {
    @Override
    public Integer call() {return 2;}
});

Now все, что вы делаете, это сказать value.get() всякий раз, когда вам нужно захватить возвращаемое значение, поток запускается в самый последний момент, когда вы даете value значение, поэтому вам никогда не придется говорить threadName.start().

Что такое Future, является обещанием для программы, вы обещаете программе, что вы получите ее значение, которое потребуется в ближайшем будущем

Если вы назовете .get() на нем до того, как это будет сделано, поток, который его вызывает, просто просто дождитесь, пока это будет сделано

5
ответ дан Electric Coffee 17 August 2018 в 21:50
поделиться
  • 1
    Я разделил предоставленный код на две вещи: один инициирует пул, который я делаю в классе Application (я говорю об android), а во-вторых, я использую пул в тех местах, где мне это нужно ... Также относительно использования Executors.newFixedThreadPool ( 2) Я использовал Executors.newSingleThreadExecutor () .., поскольку мне нужно было только одно задание, выполняемое одновременно для вызовов сервера ... Ваш ответ прекрасен @electirc coffee thanks – Gaurav Pangam 10 December 2016 в 11:07

С небольшими изменениями в вашем коде вы можете достичь этого более общим способом.

 final Handler responseHandler = new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                //txtView.setText((String) msg.obj);
                Toast.makeText(MainActivity.this,
                        "Result from UIHandlerThread:"+(int)msg.obj,
                        Toast.LENGTH_LONG)
                        .show();
            }
        };

        HandlerThread handlerThread = new HandlerThread("UIHandlerThread"){
            public void run(){
                Integer a = 2;
                Message msg = new Message();
                msg.obj = a;
                responseHandler.sendMessage(msg);
                System.out.println(a);
            }
        };
        handlerThread.start();

Решение:

  1. Создать Handler в потоке пользовательского интерфейса , который называется responseHandler
  2. Инициализируйте этот Handler из Looper раздела UI Thread.
  3. В HandlerThread сообщение post на этом responseHandler
  4. handleMessgae показывает Toast со значением, полученным от сообщения. Этот объект сообщения является общим и вы можете отправлять разные типы атрибутов.

При таком подходе вы можете отправить несколько значений в поток пользовательского интерфейса в разное время. Вы можете запустить (отправить) много Runnable объектов на этом HandlerThread, и каждый Runnable может установить значение в объекте Message, которое может быть получено в потоке пользовательского интерфейса.

21
ответ дан Ravindra babu 17 August 2018 в 21:50
поделиться

Обычно вы делаете это примерно так:

 public class Foo implements Runnable {
     private volatile int value;

     @Override
     public void run() {
        value = 2;
     }

     public int getValue() {
         return value;
     }
 }

Затем вы можете создать поток и получить значение (учитывая, что значение было установлено)

Foo foo = new Foo();
new Thread(foo).start();
// ... join through some method
int value = foo.getValue();

tl;dr нить не может вернуть значение (по крайней мере, без механизма обратного вызова). Вы должны ссылаться на поток как обычный класс и запрашивать значение.

51
ответ дан rogerdpack 17 August 2018 в 21:50
поделиться
  • 1
    Это действительно работает? Я получаю The method getValue() is undefined for the type Thread. – pmichna 26 November 2013 в 17:07
  • 2
    @pmichna, хорошее пятнистость. Переход с t.getValue() на foo.getValue(). – Johan Sjöberg 26 November 2013 в 17:46
  • 3
    Хм ... нет. Этот код неверен. Доступ к значению неправильно синхронизирован. – G. Blake Meike 14 June 2014 в 15:39
  • 4
    Да! Отлично сработано! & Quot; летучее & Quot; FTW! В отличие от принятого ответа, это правильно! – G. Blake Meike 14 June 2014 в 15:40
  • 5
    Нам действительно не нужна явная синхронизация для доступа к значению из-за гарантии согласованности памяти CountDownLatch. Создание массива значений происходит до запуска uiThread (правила порядка работы), который синхронизируется с назначением 2 в значение [0] ( thread start ), которое происходит до latch.countDown () (порядок программы правило), которое происходит раньше, чем перед защелкой.await () (гарантия от CountDownLatch), которая происходит - перед чтением из значения [0] (правило порядка программы). – Adam Zalcman 22 August 2014 в 19:09
  • 6
    Похоже, ты прав насчет Защелки! ... в этом случае синхронизация метода run бесполезна. – G. Blake Meike 22 August 2014 в 19:39
  • 7
    Хорошая точка зрения. Мне нужно скопировать код из кода OP. Исправленный. – Adam Zalcman 22 August 2014 в 19:40
  • 8
    hmm, но что, если нить не заканчивается? – Hamzah Malik 19 September 2014 в 18:44
  • 9
    @HamzahMalik Чтобы убедиться, что поток заканчивается, используйте Thread t = new Thread(foo); t.start(); t.join(); foo.getValue();. t.join() блокируется до тех пор, пока поток не будет завершен. – Daniel 16 December 2014 в 18:03
  • 10

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

Чтобы напрямую ответить на ваш вопрос, значение может быть сохранено в любой изменяемый объект, как вызывающий, так и поток, имеет ссылку. Вы можете использовать внешний this, но это не будет особенно полезно, кроме как для тривиальных примеров.

Небольшое примечание к коду в вопросе: Расширение Thread обычно плохое. , Действительно, расширение классов без необходимости - плохая идея. Я заметил, что метод run синхронизирован по какой-то причине. Теперь, поскольку объектом в этом случае является Thread, вы можете вмешиваться в то, что Thread использует свою блокировку для (в ссылочной реализации, что-то делать с join, IIRC).

4
ответ дан Tom Hawtin - tackline 17 August 2018 в 21:50
поделиться
  • 1
    & quot; тогда он должен дождаться завершения потока, что делает использование потоков немного бессмысленным & quot; отличная точка! – likejiujitsu 4 March 2013 в 21:46
  • 2
    Это обычно бессмысленно, но в Android вы не можете сделать сетевой запрос на сервер в основном потоке (чтобы поддерживать отзывчивость приложения), поэтому вам придется использовать сетевой поток. Существуют сценарии, в которых вам нужен результат, прежде чем приложение сможет возобновиться. – Udi Idan 23 October 2014 в 02:34

Java 8 обеспечивает CompletableFuture. это будет единственным решением для этого. http://www.baeldung.com/java-completablefuture

0
ответ дан Vinto 17 August 2018 в 21:50
поделиться
  • 1
    Это больше похоже на комментарий, который выступает против ответа. Не могли бы вы улучшить его с помощью примера (даже скопировать и вставить ссылку), чтобы после того, как ссылка была недействительной, люди все равно могут найти ваш ответ полезным. – Sixiang.Hu 23 February 2018 в 11:23
21
ответ дан Ravindra babu 6 September 2018 в 13:59
поделиться
22
ответ дан Ravindra babu 29 October 2018 в 20:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: