2017-02-20 3 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 
      } 
     }); 

Таким образом, это хорошая практика, чтобы использовать многопоточность, как это?

С уважением

+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 фасада, который имеет набор фабричного метода для создания часто используемых конфигураций пула потоков.

Темы есть много состояний для управления, который также определен в статье:

  • NEW: Поток, который еще не начался в этом состоянии.
  • RUNNABLE: Нить, выполняемая на виртуальной машине Java, находится в этом состоянии.
  • BLOCKED: В этом состоянии находится поток, который заблокирован в ожидании блокировки монитора.
  • WAITING: Нить, которая бесконечно ждет другого потока для выполнения определенного действия, находится в этом состоянии.
  • TIMED_WAITING: В этом состоянии поток, который ожидает неопределенный срок для другого потока для выполнения определенного действия.
  • TERMINATED: Нить, которая вышла, находится в этом состоянии.

Вот дополнительные соображения из приведенных ниже ответов на this question:

  1. Consider non-blocking I/O

    Да, вы можете запустить столько потоков, сколько вы хотите, но это, вероятно, не лучший путь. Гораздо лучше использовать неблокирующий API , чтобы вы могли приступить к выполнению какого-либо внешнего вызова, а поток может сразу начать делать что-то еще, не ожидая ответа вызова сокета/базы данных. Затем, когда вызов сокета/базы данных возвращается, для завершения этой обработки запускается обратный вызов.

    Неблокирующая I/O может обеспечить намного более высокую загрузку процессора, так как вы только инициирование вызовов и регистрации обратных вызовов и не имея попробовать , чтобы сбалансировать «правильное» количество одновременных потоков, которые в основном просто спать в любом случае ,

  2. Consider thread hierarchy

ли иерархия важна?

Возможно, вам лучше использовать ExecutorService с кэшированным пулом потоков .

Таким образом, вы можете объединять потоки вместо создания лотов (что является дорогим). ExecutorServices также предоставляют другие интересные вещи, а использование Callables/Runnables с ними, вероятно, намного проще в тестировании, чем , с помощью которого вы можете сами обмениваться файлами.

+0

Re, «_Typically, не рекомендуется напрямую создавать и управлять потоками, используя экземпляры Thread class_». Это плохой совет ИМО. Если вам нужен длинный, специализированный поток, то создание «Thread» - это самый простой способ его получить. Тем не менее, более простое == лучше, но есть случаи, когда вы, возможно, захотите использовать «ThreadFactory». Теперь мы можем спорить о том, нужно ли вам _want_ длительный специализированный поток, но это другая тема для обсуждения. –

+0

Я не знаю, достаточно ли «проще» при рассмотрении компромиссов жизненного цикла потоков, управления ресурсами, долговечности, мониторинга, стандартизации/разборчивости и т. Д. [Здесь] (http://stackoverflow.com/a/34373289/2356554) является интересным ответом на один поток против библиотеки Executor. Кроме того, прямо из Oracle есть [хорошие аргументы] (http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html), которые всегда предпочитают пакет параллелизма. – Keith

2

Нет внутренних потоков на любом языке программирования. Нити - это просто объекты с методом run() с функцией, которая может работать одновременно несколькими потоками (одновременно).

В вашем примере вы создаете две нити внутри метода Threads run(). Это не проблема, поскольку вы можете создавать объекты в любом контексте.

Если вы хотите использовать потоки, вы должны позвонить outer.start(), inner1.start() и inner2.start() после создания потоков, иначе они не будут выполнены. Опять же, это абсолютно нормально, потому что не имеет значения, в каком контексте запускается Thread; все потоки одинаково обрабатываются виртуальной машиной Java.

1

Я не предпочитаю этот путь, потому что:

* Менее читаемым

* Тема 2 автоматически подберет нить 1 приоритет, если вы не делаете установить вручную

* Планировщик потоков JVM на основе (например, временных срезах , queeuing ...), так что вы не знаете, когда поток 1 передаст текущее состояние

* Если поток 2 зависит от потока 1, вы можете достичь этой цели, используя wait, notify или другие новые функции, чтобы она была более читаемой.

Смежные вопросы