2013-06-22 3 views
14

Я использую для написания кода на JavaScript-подобных языках или в Erlang-подобных языках, где я могу легко выполнять функции обратного вызова. Теперь я должен что-то написать на Java. Я понял, как выполнить обратный вызов следующим образом:Реализация обратных вызовов в Java с помощью Runnable

import java.util.*; 

class Demo extends Thread{ 

    private int data; 

    public void run(){ 
     ask_for_data(new Runnable(){ 
      public void run(){ 
       on_data(); 
      } 
     }); 
    } 

    public void on_data(){ 
     System.out.println("Async callback: " + data); 
    } 

    public void ask_for_data(final Runnable callback){ 
     System.out.println("2"); 
     Runnable r = new Runnable(){ 
      public void run(){ 
       data = get_data(); 
       new Thread(callback).start(); 
      } 
     }; 
     new Thread(r).start(); 
    } 

    public int get_data(){ 
     try{ 
      Thread.sleep(1000); 
     } catch (Exception e) {}; 
     return 42; 
    } 

    public static void main(String[] args) { 
     Demo d = new Demo(); 
     d.start(); 
    } 
} 

Вопрос: правильно ли это?

+3

http://codereview.stackexchange.com/ – Reimeus

ответ

31

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

interface Callback { 
    void callback(); // would be in any signature 
} 

class MyThread implements Runnable { 

    Callback c; 

    public MyThread(Callback c) { 
     this.c = c; 
    } 

    public void run() { 
     // some work 
     this.c.callback(); // callback 
    } 
} 

и простой учебник о все, что нужно о потоке here

+1

Thx для учебных пособий. – zie1ony

6

Ваш код очень сложно - вы расширяете Thread, осуществлять Runnable внутри и внутри Runnable создать еще Thread. Это неправильный подход.

Runnable интерфейс можно рассматривать как команда шаблон проектирования - это единица работы, которую предстоит сделать, и он был разработан для отдельной логике «что еще предстоит сделать» из механизмов распараллеливания.

Я не знаю, правильно ли я понял вашу проблему, но из того, что я понимаю, вы просто пытаетесь передать некоторые параметры для обратного вызова, выполняемого в отдельном потоке. Поэтому почему бы просто не ввести какой-либо класс, реализующий Runnable (это ваша работа над вашей работой) и передать конструктору некоторые рабочие параметры. То, что я имею в виду то, что, как показано ниже:

public class MyUnitOfWork implements Runnable { 
    private final Data data; 

    public MyUnitOfWork(final Data data) { 
    this.data = data; 
    } 

    public void run() { 
    // do something with data 
    } 
} 

и позже:

Thread t = new Thread(new Data(/* something */)); 
t.start(); 
+0

Вы правы, но в моем случае 'MyUnitOfWork' не должен знать, что делать при обратном вызове - просто запустите его. Иногда это очень полезно. – zie1ony