【问题标题】:How to deal with multiple threads in one class?如何处理一个类中的多个线程?
【发布时间】:2010-01-17 16:51:30
【问题描述】:

线程通常以两种方式设计(see java tutorials):通过扩展 Thread 类或通过实现 Runnable 类。无论哪种方式,您都需要指定将在线程内运行的内容。

我设计了一个类,一个针对在线资源的适配器,用于检索不同类型的信息。此类由 getInformationOfTypeA() 和 getInformationOfTypeB() 等方法组成。两者都包含连接在线资源的代码,因此都需要线程化以避免死锁。

问题是:我应该如何设计这个?我可以像下面那样做,但是我只能实现一种方法:

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
  }

}

另一种方法是为每个方法创建单独的类,但这对我来说似乎不自然。

顺便说一句:我正在 j2me 中开发我的应用程序

更新:

感谢您的回复,我认为最适合使用以下方法作为方法:

你怎么看:

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

你怎么看?

【问题讨论】:

    标签: java multithreading java-me


    【解决方案1】:

    听起来你实际上应该有两个不同的类:InformationOfTypeAFetcherInformationOfTypeBFetcher,每个都应该实现 Runnable。他们每个人都可能引用您的OnlineResourceAdapter(或类似的东西)的实例,但如果他们做不同的事情,他们应该是不同的类。

    【讨论】:

      【解决方案2】:

      两个匿名的内部类,如 Thorbjørn Ravn Andersen 在上面模糊地建议的,都有效。这是一个代码示例:

      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
          }
      
      }
      

      编辑: 是的,你提出的方法是一个好方法。您甚至可以将方法设为静态。您可以使用“OnlineResourceAdapter.this”。访问其他变量以存储结果。

      【讨论】:

      • 你觉得我的匿名类版本怎么样?
      • 它应该可以工作。我不确定让这个类处理线程是否好:因为你不能从其他类控制它。作为一个快速的解决方案,它会起作用,但我不建议它作为一个长期的解决方案。也许通过方法“getInformationOfTypeARunnable()”公开 Runnable 接口,然后只返回一个可运行的。另外,当尝试从另一个线程访问它们时,不要忘记变量的同步(“volatile”关键字)。
      【解决方案3】:

      为每个类创建一个基于 Runnable 的匿名类。这将允许您在 run() 方法中执行您需要执行的操作。

      【讨论】:

        【解决方案4】:

        我不明白您为什么不喜欢创建多个类的想法,因为 Java 不支持高阶函数,而您的代码中可更改的部分是算法。

        但如果您想要 OnlineResourceAdapter 的单一实现,您可以使用策略模式并执行以下操作:

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

        当然,您可以根据需要创建任意数量的InformationGetter 实现。

        回想一下,回顾一下这种方法,OnlineResourceAdapter 现在除了使InformationGetter 可运行之外并没有真正添加任何东西。因此,除非您有一些令人信服的理由不这样做,否则我会说让 InformationGetter 直接实现 Runnable

        【讨论】:

        • 丹本赞同我的观点。策略模式是您可能想要查看的一件事。在这种情况下,拥有单独的课程对我来说似乎是一种干净的方式
        【解决方案5】:

        许多人已经提出了如何使用多个类来实现此目的的好方法。由于您似乎更喜欢不需要多个类的方式,因此您可能还需要考虑使用构造函数来提供有关要获取的资源的信息:

        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
            }
        }
        

        用法:

        (new Thread(new OnlineResourceAdapter("A"))).start();
        

        【讨论】:

        • 除非你真的,真的不得不这样做,否则不要这样做。您可以在静态类型下放置的越多越好。换句话说,有两个单独的类。
        • 另一方面,如果您可能有数千种类型的信息要检索,或者要接收的信息类型是用户输入的参数,那么使用此方法会更有意义类型作为构造函数参数,而不是为每种类型创建一个新类。在不了解海报的需求的情况下,很难说最好的解决方案是什么。
        【解决方案6】:

        使用Callable 类型的匿名类(与Runnable 相比,它可以返回值)并使用Executor 执行它们。如果检索 informationA 和 informationB 的逻辑非常相似,您当然可以对其进行重构并使用单个参数化 Callables 的内部类。

        我不确定 Callable 和 Executor 是否属于 J2ME 规范的一部分。在标准 Java 中,无论如何我都会采用Proxy 方法并将外部资源封装为接口。

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

        【讨论】:

        • 很遗憾,Java ME 中没有 java.util.concurrent
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-29
        相关资源
        最近更新 更多