2012-03-28 4 views
2

나는 루프를 허용하는 자바 쓰레드로 간단한 큐를 만들려고한다. 10 개의 반복을 가진 for 루프를 말하면, 한 번에 n 개의 쓰레드 (< 10)를 반복하고 그 쓰레드가있을 때까지 기다린다. 반복을 계속하기 전에 완료됩니다.자바 스레드의 간단한 큐

여기 내 문제를 설명하는 더 나은 방법이있다 :

for (int i = 1; i <= 10; i++) { 
    new Thread (do_some_work()); 

    if (no_available_threads) { 
     wait_until_available_threads(); 
    } 
} 

do_some_work() { 
    // do something that takes a long time 
} 

기본적으로 제가하고 싶은 것은이의 복사본입니다 : Thread and Queue

하는 방법이 가장 고통 방법을 얻을 수 있습니까?

+0

http://docs.oracle.com/javase/7/docs/api/java/util /concurrent/BlockingQueue.html은 이러한 작업에 완벽 할 것입니다. – bkowalczyyk

답변

11

나는 자신의 롤링 대신 Java 5 Executors을 사용할 것입니다. 다음과 같은 뭔가 : 다른 사람에서 권장하는

ExecutorService service = Executors.newFixedThreadPool(10); 
// now submit our jobs 
service.submit(new Runnable() { 
    public void run() { 
     do_some_work(); 
    } 
}); 
// you can submit any number of jobs and the 10 threads will work on them 
// in order 
... 
// when no more to submit, call shutdown 
service.shutdown(); 
// now wait for the jobs to finish 
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 
2

사용 실행자있는 java.util.concurrent 특히 실행자를보고 ExecutorService입니다. 그러나, 너 자신의 재미를 원한다면, 이와 같은 것을 시도해 보라. (메모장에서 작성했는데 다른 모든 것이 제대로되어 있어도 잡을 필요가있는 몇 가지 예외가 있습니다. 메모장은 코딩 오류를 잡는 데 열등합니다.) 이것은 실제 솔루션보다 개념이지만 아이디어는 일반적으로 유용 할 수 있습니다. 한편

private ConcurrentLinkedQueue<MyThread> tQueue = 
      new ConcurrentLinkedQueue<MyThread>(); 

class MyThread extends Thread { 
    public Runnable doSomething; 

    public void run() { 
     // Do the real work. 
     doSomething(); 
     // Clean up and make MyThread available again. 
     tQueue.add(mythread); 
     // Might be able to avoid this synch with clever code. 
     // (Don't synch if you know no one's waiting.) 
     // (But do that later. Much later.) 
     synchronized (tQueue) { 
      // Tell them the queue is no longer empty. 
      tQueue.notifyAll(); 
     } 
    } 
} 

는 :

또한
// Put ten MyThreads in tQueue. 
for (int i = 0; i < 10; i++) tQueue.add(new MyThread()); 

// Main Loop. Runs ten threads endlessly. 
for (;;) { 
    MyThread t = tQueue.poll(); 
    if (t == null) { 
     // Queue empty. Sleep till someone tells us it's not. 
     do { 
      // There's a try-catch combo missing here. 
      synchonized(tQueue) { tQueue.wait() }; 
      t = tQueue.poll(); 
     } while (t == null) break; // Watch for fake alert! 
    } 
    t.doSomething = do_some_work; 
    t.start(); 
} 

, ConcurrentLinkedQueue를의 현명한 사용을 확인합니다. ArrayList 또는 LinkedList와 같은 다른 것을 사용할 수도 있지만 동기화해야합니다.

+0

ConcurrentLinkedQueue를 사용하고 있습니다. 왜 동기화하고 있습니까? – MikeB

0

나무 상자 Logger.class :

public class Logger extends Thread { 
    List<String> queue = new ArrayList<String>(); 
    private final int MAX_QUEUE_SIZE = 20; 
    private final int MAX_THREAD_COUNT = 10; 

    @Override 
    public void start() { 
     super.start(); 
     Runnable task = new Runnable() { 
      @Override 
      public void run() { 
       while (true) { 
        String message = pullMessage(); 
        Log.d(Thread.currentThread().getName(), message); 
        // Do another processing 
       } 
      } 
     }; 
     // Create a Group of Threads for processing 
     for (int i = 0; i < MAX_THREAD_COUNT; i++) { 
      new Thread(task).start(); 
     } 
    } 

    // Pulls a message from the queue 
    // Only returns when a new message is retrieves 
    // from the queue. 
    private synchronized String pullMessage() { 
     while (queue.isEmpty()) { 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
      } 
     } 
     return queue.remove(0); 
    } 

    // Push a new message to the tail of the queue if 
    // the queue has available positions 
    public synchronized void pushMessage(String logMsg) { 
     if (queue.size() < MAX_QUEUE_SIZE) { 
      queue.add(logMsg); 
      notifyAll(); 
     } 

    } 
} 

그런 다음 메인 클래스에서 울부 짖는 코드를 삽입 :

Logger logger =new Logger(); 
logger.start(); 
for (int i=0; i< 10 ; i++) { 
    logger.pushMessage(" DATE : "+"Log Message #"+i); 
}