2015-06-24 1 views
0

Я пытаюсь создать приложение, которое будет создавать потоки в дереве подобно манере. Мой основной метод находится на Level0, который создает поток в Level1. Затем Level1 создаст некоторые потоки. Каждый поток в Level1 будет создавать разные наборы потоков как Level2 и так далее.Создание потоков с несколькими уровнями в иерархическом порядке

Ниже код, который я пытаюсь использовать, используя ExecutorService:

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 
import java.util.Map; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class ThreadTree { 

public static void main(String[] args) { 
ExecutorService exec = Executors.newCachedThreadPool(); 

//This is the main , level0 

List ll = new ArrayList<>(); 
ll.add(2); 
ll.add(5); 
ll.add(8); 

Iterator it = ll.iterator(); 
while (it.hasNext()) { 

    exec.submit(new Level1((Integer)it.next())); 
} 
} 
} 

class Level1 implements Runnable{ 

private ScheduledExecutorService exec; 
private Integer num; 

public Level1(Integer n){ 
    num = n; 
    exec = Executors 
      .newScheduledThreadPool(n); 
} 

@Override 
public void run() { 

    for(int i=0;i<num;i++){ 
     exec.scheduleAtFixedRate(new Level2(), 0, 2, TimeUnit.SECONDS); 
    } 


} 

} 

class Level2 implements Runnable{ 

@Override 
public void run() { 

    System.out.println("Current Thread ID : " + Thread.currentThread().getId() + "Current Thread Name : " 
      + Thread.currentThread().getName()) ; 
    //Do some task and create new threads 

} 

} 

У меня 2 вопроса:

  1. Это единственный подход к созданию потоков в дереве образом? Существуют ли какие-либо другие способы эффективного решения этой проблемы, с некоторыми группировками? Я показал 3 уровня, но также может быть больше уровней.
  2. В случае, это хороший способ, что является лучшим способом распространения любого сбоя в потоке на одном из уровней над слоем над ним и т. Д.

Заранее спасибо.

+0

Обычно Threads используются для асинхронных задач, которые не выводятся из этих ресурсов другим ресурсам. Итак, вы уверены, что вам нужно создать поток, который уже находится внутри потока? –

+0

Вы сталкивались с группами нитей? например http://www.javaworld.com/article/2074481/java-concurrency/java-101--understanding-java-threads--part-4---thread-groups--volatility--and-threa.html? –

+0

@ user1354678 - У нас есть сценарий, где мы хотим обрабатывать данные для сотрудников для разных компаний. Теперь у каждой компании будут разные отделы, и у каждого из разных отделов будут сотрудники. Мы хотим обрабатывать 1 поток на одного сотрудника, а уровни может отличаться. – Anupam

ответ

1

Я думаю, что вы можете достичь этого, выполнив действия, описанные ниже -

  • Используя только один пул потоков Исполнителю
  • Создание механизма уведомления от дочернего задания для родителей. (Обратите внимание задачи отличается нитью Задача просто Runnable объекта, а Thread является Java потоком, который выполняет исполняемую задачу по исполнителю..)

Пожалуйста, обратитесь образцом ниже -

public class ThreadTree { 

private static final ExecutorService executor = Executors.newCachedThreadPool(); 

public static void main(String[] args) { 
    List<Integer> level1Nodes = new ArrayList<Integer>(); 
    level1Nodes.add(2); 
    level1Nodes.add(5); 
    level1Nodes.add(8); 
    // start threads 
    for (Integer num : level1Nodes) { 
     executor.submit(new Level1(num)); 
    } 
} 

private static class Notification { 
    private final Object result; 
    private final Exception rootException; 

    public Notification(Object result, Exception rootException) { 
     this.result = result; 
     this.rootException = rootException; 
    } 

    public Object getResult() { 
     return result; 
    } 

    public Exception getRootException() { 
     return rootException; 
    } 
} 

private static abstract class NotificationHandler { 
    private final AtomicInteger expectedNotifications; 
    private final List<Notification> notifications; 

    public NotificationHandler(int expectedNotifications) { 
     this.expectedNotifications = new AtomicInteger(expectedNotifications); 
     this.notifications = new ArrayList<Notification>(); 
    } 

    public void handleNotification(Notification notification) { 
     notifications.add(notification); 
     if (expectedNotifications.decrementAndGet() == 0) { 
      postRun(notifications); 
     } 
    } 

    public void postRun(List<Notification> notifications) { 
     for (Notification notification : notifications) { 
      System.out.println("Status: " + (notification.getRootException() == null ? "Failed" : "Success") + ", Result: " + (notification.getResult() != null ? notification.getResult() : "No result")); 
     } 
    } 
} 

private static class Level1 extends NotificationHandler implements Runnable { 
    private final int num; 

    public Level1(int num) { 
     super(num); 
     this.num = num; 
    } 

    public void run() { 
     for (int i = 0; i < num; i++) { 
      executor.submit(new Level2(2, this)); // 2 is just an assumed number of nodes at level 2 
     } 
    } 
} 

private static class Level2 extends NotificationHandler implements Runnable { 
    private final int num; 
    private final NotificationHandler parentNotificationHandler; 

    public Level2(int num, NotificationHandler parentNotificationHandler) { 
     super(num); 
     this.num = num; 
     this.parentNotificationHandler = parentNotificationHandler; 
    } 

    public void run() { 
     for (int i = 0; i < num; i++) { 
      executor.submit(new Level2(2, this)); // 2 is just an assumed number of nodes at level 3 
     } 
     // execute the task and then notify parent 
     parentNotificationHandler.handleNotification(new Notification("done", null)); 
    } 
} 

private static class Level3 extends NotificationHandler implements Runnable { 
    private final int num; 
    private final NotificationHandler parentNotificationHandler; 

    public Level3(int num, NotificationHandler parentNotificationHandler) { 
     super(num); 
     this.num = num; 
     this.parentNotificationHandler = parentNotificationHandler; 
    } 

    public void run() { 
     // execute the task and then notify parent 
     parentNotificationHandler.handleNotification(new Notification("done", null)); 
    } 
} 
} 

Здесь Notification передается от Level3 ->Level2' -> Level1 '. Каждая детская задача обязана уведомлять родителя, как только это делается с его собственной работой. После того как все дочерние задачи уведомили родительскую задачу, будут выполняться действия после запуска и уведомить ее родителя.

Здесь не имеет значения, какие темы используются в исполнителе потоков. Единственное, что имеет значение, это следовать правилу уведомления родителя по каждой дочерней задаче, а затем родитель, выполняющий почтовые действия, и дальнейший уведомление его родителя.

Notification класс состоит из result и rootException, который может быть установлен из дочерней задачи, чтобы родитель мог знать, что пошло не так в дочерней задаче, и исключение может перемещаться на верхний уровень.

+0

Большое спасибо ... Я собираюсь принять это как свой ответ .. – Anupam