views:

201

answers:

6

Threads are often designed in two ways (see java tutorials): either by extending the Thread class or by implementing the Runnable class. Either way, you need to specify what will run inside the thread.

I designed a class, an adapter towards an online resource, that retrieves different kinds of information. This class consists of methods like getInformationOfTypeA() and getInformationOfTypeB(). Both contain code to connect to online resources, so both need to be threaded to avoid deadlocks.

The question is: how should I design this? I can do it like below, but then I can only implement one method:

public class OnlineResourceAdapter implements Runnable {

  public void run() {
      //get stuff from resource
      getInformationOfTypeA();
  }

  public static void main(String args[]) {
      (new Thread(new OnlineResourceAdapter ())).start();
  }

  public void getInformationOfTypeA(){
      //get information of type A
  }

  public void getInformationOfTypeB(){
      //get information of type B
  }

}

Another way would be by creating separate classes for each method, but that seems unnatural to me.

Btw: I'm developing my application in j2me

UPDATE:

Thanks to your responses I think it is most suiting to use something like the following as methods:

What do you think of this:

public class OnlineResourceAdapter{
    public void getInformationOfTypeA(){
        Thread t = new Thread(new Runnable() {           
            public void run() { 
                //do stuff here
            } 
        });
        t.start();
    }

    public void getInformationOfTypeB(){
        Thread t = new Thread(new Runnable() {           
            public void run() { 
                //do stuff here
            } 
        });
        t.start();
    }
}

What do you think of this?

+1  A: 

For each class create an anonymous class based on Runnable. This will allow you to do what you need to do inside the run() method.

Thorbjørn Ravn Andersen
+5  A: 

It sounds to me like you should actually have two different classes: InformationOfTypeAFetcher and InformationOfTypeBFetcher, each of which should implement Runnable. Each of them may have a reference to an instance of your OnlineResourceAdapter (or something similar) but if they're doing different things, they should be different classes.

Jon Skeet
+1  A: 

I don't see why you don't like the idea of creating multiple classes, considering Java doesn't support higher-order functions and the changeable part of your code is the algorithm.

But if you wanted a single implementation of OnlineResourceAdapter you could use the Strategy pattern and do something like this:

public interface InformationGetter {
  public void getInformation();
}

public class OnlineResourceAdapter implements Runnable {
  private final InformationGetter informationGetter;

  public OnlineResourceAdapter(InformationGetter i) {
    this.informationGetter = i;
  }

  public void run() {
      //get stuff from resource
      i.getInformation();
  }
}

and then of course you would create as many implementations of InformationGetter as you needed.

Come to think about it, looking back over this approach, OnlineResourceAdapter now doesn't really add anything except making InformationGetter runnable. So unless you have some compelling reason not to, I would say just have InformationGetter implement Runnable directly.

danben
danben echoes my opinion. Strategy pattern is one thing you might want to look at. Having Separate classes looks like a clean way to me in this case
Aadith
+1  A: 

Many people have already suggested good methods of how to do this using several classes. Since you seem to prefer a way which doesn't require multiple classes, you might also want to consider using the constructor to give information about which resource to fetch:

public class OnlineResourceAdapter implements Runnable
{
    private string resourceType;

    public OnlineResourceAdapter(string resourceType)
    {
        this.resourceType = resourceType;
    }

    public void run() {
        if (resourceType.equals("A") {
            getInformationOfTypeA();
        } else {
            // etc..
        }
    }

    public void getInformationOfTypeA(){
        //get information of type A
    }

    public void getInformationOfTypeB(){
        //get information of type B
    }
}

Usage:

(new Thread(new OnlineResourceAdapter("A"))).start();
Mark Byers
Unless you really, really have to then don't do this. The more you can put under static typing, the better. In other words, have two separate classes.
Thorbjørn Ravn Andersen
On the other hand, if you have potentially thousands of types of information to retrieve, or the type of information to receive is a parameter that the user enters, this method would make a lot more sense to have the type as a constuctor parameter than creating a new class for each type. Without knowing more about the poster's needs, it's hard to say what the best solution is.
Mark Byers
A: 

Use anonymous classes of type Callable (which, in contrast to Runnable, can return values) and execute them using an Executor. If the logic to retrieve informationA and informationB is very similar, you may of course refactor that and use a single, parameterizes inner class of Callables.

I'm not sure if Callable and Executor are part of J2ME spec though. In standard Java, i'd go for a Proxy approach anyway and encapsulate the external resource as interface.

public class AsyncMethodsTest {

    public class OnlineResourceAdapter {

        private final ExecutorService executor = Executors.newFixedThreadPool(2);

        public String getInformationOfTypeA() throws InterruptedException, ExecutionException,
                TimeoutException {
            Callable<String> callable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    // Connect to external resource
                    Thread.sleep(500);
                    return "A";
                }

            };
            Future<String> submit = executor.submit(callable);
            return submit.get(1000, TimeUnit.MILLISECONDS);
        }

        public String getInformationOfTypeB() throws InterruptedException, ExecutionException,
                TimeoutException {
            Callable<String> callable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    // Connect to external resource
                    Thread.sleep(1500);
                    return "B";
                }

            };
            Future<String> submit = executor.submit(callable);
            return submit.get(1000, TimeUnit.MILLISECONDS);
        }

    }

    @Test
    public void testMethodCalls() throws Exception {
        OnlineResourceAdapter adapter = new OnlineResourceAdapter();
        assertNotNull(adapter.getInformationOfTypeA());
        assertNotNull(adapter.getInformationOfTypeB());
    }
}
mhaller
Unfortunately, there's no `java.util.concurrent` in Java ME.
BalusC
+2  A: 

Two anonymous inner classes, like Thorbjørn Ravn Andersen suggested vaguely above, works. Here is a code example:

public class OnlineResourceAdapter {

    public final Runnable typeA;
    public final Runnable typeB;

    public OnlineResourceAdapter() {
        typeA = new Runnable() {
            public void run() {
                OnlineResourceAdapter.this.getInformationOfTypeA();
            }
        };
        typeB = new Runnable() {
            public void run() {
                OnlineResourceAdapter.this.getInformationOfTypeB();
                // one can use a non-final typed variable
                // to store, which then<1>
            }
        };
    }

    public static void main(String args[]) {
        OnlineResourceAdapter x = new OnlineResourceAdapter();
        new Thread(x.typeA).start(); // start A
        new Thread(x.typeB).start(); // start B
        // <1>can be accessed here.
    }

    public void getInformationOfTypeA(){
        // get information of type A
        // return the data or directly store in OnlineResourceAdapter.
    }

    public void getInformationOfTypeB(){
        //get information of type B
    }

}

Edit: Yes, you're proposed way is a good way. You can even make the methods static. You can use "OnlineResourceAdapter.this." to access other variables to store results in.

Pindatjuh
what do you think of my version of anonymous classes?
hsmit
It should work. I'm not sure whether it's good to let this class handle the threading: since you can't control it from other classes then. As a quick solution, it would work, but I wouldn't advice it as a long-term solution.Perhaps expose the Runnable interface by methods "getInformationOfTypeARunnable()", which then only returns a runnable. Also, don't forget synchronization of variables ("volatile" keyword), when trying to access them from another thread.
Pindatjuh