2017-02-20 61 views
1

根据标题,看一下这个代码:在另一个线程中使用线程是否是一个好习惯?

Thread outer = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       Thread inner1 = new Thread(new Runnable() { 
        @Override 
        public void run() { 
         //some statements and other inner threads 
        } 
       }); 

       Thread inner2 = new Thread(new Runnable() { 
        @Override 
        public void run() { 
         //some statements and other inner threads 
        } 
       }); 

       //some statements and other inner threads 
      } 
     }); 

所以,这是一个好的做法是使用多线程这样吗?

Regards

+1

请尝试坚持每个问题1个问题。 – Kayaman

+0

@Kayaman对不起...我只是不想发3帖子。如果它不好,我会编辑它并发送另外2个帖子。我应该这样做吗? – HMD

+0

那么目前这个问题有点太大,无法正确回答。 – Kayaman

回答

1

根据Q1“很好”。这是正确的,但创建威胁只是为了创建另一个线程没有多大意义。

另外,请记住,创建一个Thread对象是相对昂贵的操作。 您在代码中有//some statements and other inner threads评论。考虑使用ThreadPoolExecutor来避免手动创建多个线程。

1

Java Code Geeks关于并发性的文章对您有几点建议。我建议你将其全部读它,但这里有两个重要的片段:

通常情况下,不建议直接创建和管理使用Thread类的实例线程...

和这个:

在Java中创建新线程很简单,但管理它们真的很难。 Java标准库提供了极其有用的抽象概念,其执行者和线程池的形式可以简化线程管理。

实质上,在其最简单的实现中,线程池创建并且维护一个线程列表,准备马上使用。 应用程序,而不是每次产生新的线程,只是从池中借用 (或根据需要)。一旦借用线程 完成其作业,它将返回到池中,并且变为 可用于接收下一个任务。

虽然可以直接使用线程池,Java标准 库提供一个executors外观,其具有一组工厂方法 的创建常用线程池配置。

线程有很多国家的管理,这也是在文章中确定:

  • :尚未启动的线程处于这种状态。
  • RUNNABLE:在Java虚拟机中执行的线程处于此状态。
  • BLOCKED:阻塞等待监视器锁定的线程处于此状态。
  • WAITING:无限期等待另一个线程执行特定操作的线程处于此状态。
  • TIMED_WAITING:无限期等待另一个线程执行特定操作的线程处于此状态。
  • TERMINATED:已退出的线程处于此状态。

以下是一些其他方面的考虑,从下面的答案this question

  1. Consider non-blocking I/O

    是的,你可以根据需要推出尽可能多的线程,但是这可能 不是最好的要走的路。使用非阻塞API的 好得多,这样你就可以开始执行一些外部调用,并且调用线程可以立即开始做其他事情,而不用等待 socket /数据库调用返回。然后,当套接字/数据库 调用回来时,会触发回调来完成该处理。

    非阻塞因为你 只是触发呼叫和注册回调,并没有尝试 平衡并发线程基本都是 只是在睡觉反正的“正确”数字I/O能够提供远远优于CPU利用率。

  2. Consider thread hierarchy

是层次很重要?

您可能最好使用ExecutorService和缓存的 线程池。

这种方式可以将线程池​​而不是创建批次(这是昂贵的 )。 ExecutorServices还提供了其他很酷的功能,并且使用它们的Callables/Runnables可能比使用自己的线程更容易测试。

+0

Re,“通常,不建议使用Thread class_实例直接创建和管理线程。”这是IMO的不好建议。如果你想要一个长期运行的专用线程,那么实例化'Thread'就是获得它的最简单方法。尽管更简单==好,但是,您可能希望使用'ThreadFactory'来代替。现在,我们可以争论你是否应该运行一个长期运行的专业化线程,但这是另一个需要讨论的话题。 –

+0

我不知道是否“更简单”在考虑线程生命周期,资源管理,持久性,监控,标准化/易读性等方面的权衡时具有足够的权重。[Here](http://stackoverflow.com/a/34373289/2356554)是关于单个线程与Executor库有关的有趣答案。另外,直接从Oracle获得[良好参数](http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html)总是更喜欢并发包。 – Keith

2

在任何编程语言中都没有内部线程。线程只是具有run()方法的对象,具有几个线程可以同时运行(同时)的功能。

在您的示例中,您在线程的run()方法内创建了两个线程。这不是问题,因为您可以在任何上下文中创建对象。

如果你想使用线程,你必须在创建线程之后调用outer.start(),inner1.start()inner2.start(),否则它们不会被执行。再说一次,这绝对没问题,因为Thread在哪个上下文中开始并不重要;所有线程均由Java虚拟机平等对待。

1

我不喜欢这种方式,因为:

*的可读性

*线程2将自动挑选线程1优先,除非你不手动

*线程调度基于JVM(如时间段设置,排队......),所以你不知道线程1何时会通过可运行状态

*如果线程2依赖线程1,则可以使用wait和notify或其他新功能来实现此目标,以便它更易读

相关问题