How to deal with multiple threads in one class?

后端 未结 6 1270
醉酒成梦
醉酒成梦 2021-02-04 12:31

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 wil

相关标签:
6条回答
  • 2021-02-04 13:04

    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.

    0 讨论(0)
  • 2021-02-04 13:08

    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.

    0 讨论(0)
  • 2021-02-04 13:08

    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.

    0 讨论(0)
  • 2021-02-04 13:11

    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());
        }
    }
    
    0 讨论(0)
  • 2021-02-04 13:23

    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();
    
    0 讨论(0)
  • 2021-02-04 13:26

    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.

    0 讨论(0)
提交回复
热议问题