2017-01-31 11 views
0

Мне немного стыдно задавать этот основной вопрос, но вот оно.Java: вызов обратного вызова из другого потока, в контексте исходной темы

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

Теперь с чем я борюсь: обратный вызов основного класса выполняется как часть рабочего потока. Я сделал это дюжину раз, и это никогда не вызывало никаких проблем для меня, но мне интересно, как элегантно передать ответ от рабочего потока на фактический основной поток.

Я знаю, что могу использовать Future и FutureTask и т. Д., Но мне это кажется неуклюжим.

Пример:

class ThreadTest { 
     private Runnable mRunnable; 

     public ThreadTest() { 
       System.out.println("ThreadTest(): thread " + Thread.currentThread().getId()); 
       mRunnable = new Runnable() { 
         public void run() { 
           System.out.println("run(): thread " + Thread.currentThread().getId()); 
           print(); 
         } 
       }; 
       new Thread(mRunnable).start(); 
     } 
     private void print() { 
       System.out.println("print(): thread " + Thread.currentThread().getId()); 
     } 
     public static void main(String... args) { 
       System.out.println("main(): thread " + Thread.currentThread().getId()); 
       ThreadTest t = new ThreadTest(); 
     } 
} 

Выход:

main(): thread 1 
ThreadTest(): thread 1 
run(): thread 9 
print(): thread 9 

То, что я хотел бы получить:

main(): thread 1 
ThreadTest(): thread 1 
run(): thread 9 
print(): thread 1 
+0

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

+0

Не обращайте внимания; -.) – GhostCat

ответ

1

Одно общее решение таких проблем является создание "канала связи" между основной и рабочей нитью.

Другими словами: вы помещаете структуру данных между тем, что одна сторона может писать, а другая сторона может читать.

И общий способ сделать это - использовать ConcurrentLinkedQueue. См. here для дальнейшего чтения; включая простой сценарий производителя/потребителя.

Помимо этого, вы должны быть более четкими в своем дизайне. То, что я имею в виду: я бы либо сосредоточиться на

  1. рабочий поток, который делает что-то, и выдает результат (для «поднять его»), используя Future
  2. Некоторые нити B инициирующего обратный вызов на ваш главный нить в какой-то момент.

Другими словами: это можно рассматривать как «тянуть» (используя будущее) или «нажимать» (поток B, вызывающий метод обратного вызова). Я предлагаю выбрать для одну концепцию, а не использовать «50%» двух концепций одновременно!

1

Наименее сложное решение для этого было бы использовать wait() и notify().

Как побочное замечание, я бы сказал, что в будущем нет никаких сомнений относительно будущего, особенно если мы говорим о java8 и CompletableFuture.

+0

Согласитесь, нет ничего сугубо неуклюжий в отношении фьючерсов. – Kayaman

 Смежные вопросы

  • Нет связанных вопросов^_^