2012-05-22 5 views
0

Java에서 다중 스레드 알고리즘을 작성하는 데 약간의 문제가 있습니다. 여기에 내가있어 무엇 :Java의 스레드가 동시에 시작하지 않고 순차적으로 실행됩니다.

public class NNDFS implements NDFS { 

//Array of all worker threads 
private Thread[] threadArray; 

//Concurrent HashMap containing a mapping of graph-states and 
//algorithm specific state objects (NDFSState) 
private ConcurrentHashMap<State, NDFSState> stateStore; 

//Whether the algorithm is done and whether a cycle is found 
private volatile boolean done; 
private volatile boolean cycleFound; 


/** 
    Constructor that creates the threads, each with their own graph 

    @param file  The file from which we can create the graph 
    @param stateStore Mapping between graph-states and state belonging to our algorithm 
    @param nrWorkers Number of working threads we need 
*/ 
public NNDFS(File file, Map<State, NDFSState> stateStore, int nrWorkers) throws FileNotFoundException { 
    int i; 
    this.stateStore = new ConcurrentHashMap<State, NDFSState>(stateStore); 
    threadArray = new Thread[nrWorkers]; 
    for(i=0;i<nrWorkers;i++){ 
     Graph graph = GraphFactory.createGraph(file); 
     threadArray[i] = new Thread(new NDFSRunnable(graph, i)); 
    } 
} 

/** 
    Class which implements a single thread running the NDFS algorithm 
*/ 
class NDFSRunnable implements Runnable{ 

    private Graph graph; 

    //Neccesary as Java apparently doesn't allow us to get this ID 
    private long threadId; 

    NDFSRunnable(Graph graph, long threadId){ 
     this.graph = graph; 
     this.threadId = threadId; 
    } 

    public void run(){ 
     try { 
      System.out.printf("Thread id = %d\n", threadId); 
      //Start by executing the blue DFS for the first graph 
      mcdfsBlue(graph.getInitialState(), threadId); 
     } catch (CycleFound e) { 
      //We must catch all exceptions that are thrown from within our thread 
      //If exceptions "exit" the thread, the thread will silently fail 
      //and we dont want that. We use 2 booleans instead, to indicate the status of the algorithm 

      cycleFound = true; 
     } 

     //Either the algorithm was aborted because of a CycleFound exception 
     //or we completed our Blue DFS without finding a cycle. We are done! 
     done = true; 
    } 

    public void mcdfsBlue(State s, long id) throws CycleFound { 
     if(done == true){ 
      return; 
     } 
     //System.out.printf("Thread %d begint nu aan een dfsblue\n", id); 
     int i; 
     int counter = 0; 
     NDFSState state = stateStore.get(s); 
     if(state == null){ 
       state = new NDFSState(); 
       stateStore.put(s,state); 
     } 
     state.setColor(id, Color.CYAN); 
     List<State> children = graph.post(s); 
     i = state.incNextBlue(); 
     while(counter != children.size()){ 
      NDFSState child = stateStore.get(children.get(i%children.size())); 

      if(child == null){ 
        child = new NDFSState(); 
        stateStore.put(children.get(i % children.size()),child); 
      } 
      if(child.getLocalColor(id) == Color.WHITE && !child.isRed()){ 

       mcdfsBlue(children.get(i % children.size()), id); 
      } 
      i++; 
      counter++; 
     } 
     if(s.isAccepting()){ 
      state.incRedDFSCount(); 
      mcdfsRed(s, id); 
     } 
     state.setColor(id, Color.BLUE); 
    } 

    public void mcdfsRed(State s, long id) throws CycleFound { 
     if(done == true){ 
      return; 
     } 
     int i; 
     int counter = 0; 
     NDFSState state = stateStore.get(s); 
     state.setPink(id, true); 
     List<State> children = graph.post(s); 
     i = state.incNextRed(); 
     while(counter != children.size()){ 
      NDFSState child = stateStore.get(children.get(i%children.size())); 
      if(child == null){ 
        child = new NDFSState(); 
        stateStore.put(children.get(i%children.size()),child); 
      } 
      if(child.getLocalColor(id) == Color.CYAN){ 
       throw new CycleFound(); 
      } 
      if(!child.isPink(id) && !child.isRed()){ 
       mcdfsRed(children.get(i%children.size()), id); 
      } 
      i++; 
      counter++; 
     } 
     if(s.isAccepting()){ 
      state.decRedDFSCountAndWait(); 
     } 
     state.setRed(); 
     state.setPink(id, false); 
    } 

} 

public void init() {} 

public void ndfs() throws Result { 
    int i; 
    done  = false; 
    cycleFound = false; 
    for(i=0;i<threadArray.length;i++){ 
      System.out.printf("Launch thread %d\n",i); 
      threadArray[i].run(); 
    } 

    try { 
     for(i=0;i<threadArray.length;i++){ 
      threadArray[i].join(); 
     } 
    } catch (InterruptedException e) { 

    } 

    //We want to show the result by throwing an exception (weird, but yeah :-/) 
    if (cycleFound) { 
     throw new CycleFound(); 
    } else { 
     throw new NoCycleFound(); 
    } 
}        

}

내가 이것을 실행할 때, 그것은 내가 분명히 원하는 것은 등 첫 번째 스레드가 호출처럼, 그리고 그 다음이라고 완료된 것 같다, 모든 스레드가 동시에 시작된다는 것입니다! 그렇지 않으면 알고리즘이 거의 사용되지 않습니다.

시간 내 주셔서 감사합니다/도움!

감사합니다,

리누스

+4

당신은'.run()'대신'threadArray [i] .start();'를 호출하는 것을 의미합니까? –

+0

결과를 반환하는 예외를 던지고 있습니까? 그렇게하는 것에 익숙해하지 마라, 그것은 단지 잘못한 것이다. –

+0

@SoboLAN 예, 알겠습니다. 이것은 우리가 제공 한 프레임 워크의 개선입니다. 우리는 그것에 대해 만족하지 않습니다 ... – Linus

답변

9

사용 threadArray[i].start();는 스레드를 시작합니다.

threadArray[i].run();을 사용하는 경우 호출자와 동일한 스레드에서 메서드 호출이 정상적으로 수행됩니다.

+0

예! 고마워, 어리석은 실수. – Linus

관련 문제