在另一个线程中使用线程是一个好习惯吗?

时间:2017-02-20 16:45:53

标签: java multithreading

根据标题,看看这段代码:

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

那么,使用这样的多线程是一个好习惯吗?

此致

4 个答案:

答案 0 :(得分:2)

任何编程语言都没有内部线程。线程只是具有sort -n $pngTotal $gifTotal方法的对象,其特点是多个线程可以同时运行(并发)。

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

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

这篇关于并发性的Java Code Geeks文章为您提供了一些建议。我建议你完整阅读它,但这里有两个重要的片段:

  

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

和此:

  

在Java中创建新线程很简单,但管理它们确实很简单   强硬。 Java标准库提供了非常有用的抽象   用于简化线程的执行程序和线程池的形式   管理。

     

基本上,在最简单的实现中,线程池创建和   维护一个线程列表,随时可以使用。   应用程序,而不是每次产生新的线程,只是借用   池中的一个(或多个需要的)。一旦借来的线程   完成它的工作,它返回到池中,并成为   可以接受下一个任务。

     

虽然可以直接使用线程池,但Java标准   library提供了一个executorsfaçade,它有一套工厂方法   创建常用的线程池配置。

线程有很多要管理的状态,这也在文章中指出:

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

以下是this question的答案中的其他注意事项:

  1. Consider non-blocking I/O

      

    是的,您可以根据需要启动任意数量的线程,但这可能是   不是最好的方式。使用非阻塞API会好得多   这样你就可以开始执行一些外部呼叫和呼叫了   线程可以立即开始做其他事情而无需等待   socket / database调用回来。然后,当socket /数据库   呼叫返回,触发回调以完成处理。

         

    非阻塞I / O可以提供更高的CPU利用率,因为您   只是触发调用和注册回调而不必尝试   平衡大多数并发线程的“正确”数量   只是睡觉了。

  2. Consider thread hierarchy

  3.   

    层次结构是否重要?

         

    使用带有缓存的ExecutorService可能会更好   线程池。

         

    这样你就可以汇集线程而不是创建批量(这是   昂贵)。 ExecutorServices还提供其他很酷的东西,并使用   使用Callables / Runnables可能比测试更容易   用你自己的线程来捣乱。

答案 3 :(得分:1)

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

*不太可读

*除非你手动设置

,否则线程2会自动选择线程1优先级

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

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