How to deal with multiple threads in one class?

…衆ロ難τιáo~ 提交于 2019-12-03 12:32:33

问题


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:


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.




回答2:


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.




回答3:


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.




回答4:


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.




回答5:


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();



回答6:


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());
    }
}


来源:https://stackoverflow.com/questions/2081747/how-to-deal-with-multiple-threads-in-one-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!