2014-09-04 58 views
0

這是Java 7 Concurrency Cookbook的練習。目標是讓多個生產者將事件寫入共享隊列,並且清理任務(守護進程線程)將從隊列中刪除超過5秒的事件。(查找代碼如下) 如果我嘗試爲此編寫測試或在main()程序,它只在隊列中插入3個項目並退出。 我的問題:如果WriterTask中存在for循環,爲什麼程序不運行for循環(在隊列中插入〜30項)並在此之前退出?多個生產者不能正常工作

import java.util.Date; 
import java.util.Deque; 
import java.util.concurrent.TimeUnit; 
class Event{ 
    Date var; 
    public Event(Date v){ 
     var = v; 
    } 
} 
class WriterTask implements Runnable{ 
    Deque<Event> queue; 
    int from = 0,to = 0; 
    public WriterTask(Deque<Event> queue, int from, int to){ 
     this.queue = queue; 
     this.from = from; 
     this.to = to; 
    } 
    @Override 
    public void run(){ 
     for(int i=from;i<to;i++){ 
      Event ev = new Event(new Date()); 
      System.out.println("Generating event number: "+i); 
      queue.addFirst(ev); 
      try{ 
       System.out.println("SLeeping now:"+Thread.currentThread().getName()); 
       TimeUnit.SECONDS.sleep(1); 
      }catch(InterruptedException ie){ 
       System.out.println("Interrupted the thread!"); 
      } 
     } 
    } 
} 


class CleanerTask implements Runnable{ 
    Deque<Event> queue; 

    public CleanerTask(Deque<Event> queue){ 
     this.queue = queue; 
    } 
    @Override 
    public void run(){ 
     while(true){ 
      Date dt = new Date(); 
      clean(dt); 
     } 
    } 

    public void clean(Date date){ 
//  System.out.println("Cleaning for date, current size of queue:"+queue.size()); 
     long difference = 0; 
     boolean anythingDeleted = false; 
     do{ 
      if(queue.isEmpty()){return;} 
      Event first = queue.getLast(); 
      difference = date.getTime() - first.var.getTime(); 
      if(difference > 5000){ 
       queue.removeLast(); 
       anythingDeleted = true; 
      } 
     }while(difference>5000); 
     if(anythingDeleted){ 
      System.out.println("Queue cleaned up, new size:"+queue.size()); 
     } 
    } 
} 

測試:

import org.junit.Test; 
import org.junit.rules.Timeout; 

import java.util.ArrayDeque; 
import java.util.Deque; 
import java.util.LinkedList; 
public class WriterCleanerTest { 
    @Test 
    public void consumeCleanTest(){ 
     Deque<Event> queue = new ArrayDeque<Event>(); 
     WriterTask wt = new WriterTask(queue, 0, 10); 
     Thread wt1 = new Thread(wt); 
     Thread wt2 = new Thread(new WriterTask(queue, 60, 70)); 
     Thread wt3 = new Thread(new WriterTask(queue, 100, 110)); 

     wt1.start(); 
     wt2.start(); 
     wt3.start(); 

     System.out.println("Size of queue:"+queue.size()); 

     Thread cleanerTask = new Thread(new CleanerTask(queue)); 
     cleanerTask.setDaemon(true); 
     cleanerTask.start(); 
    } 
} 

輸出:

Size of queue:0 
Final Size of queue:0 
Generating event number: 0 
Generating event number: 60 
SLeeping now:Thread-1 
Generating event number: 100 
SLeeping now:Thread-2 
SLeeping now:Thread-0 

Process finished with exit code 0 

回答

0

你是不是在等待你的線程來完成。

添加在你的代碼的末尾:

cleanerTask.start(); 
// Wait for everything to finish. 
wt1.join(); 
wt2.join(); 
wt3.join(); 
cleanerTask.join(); 

本質上你的主線程必須join所有其他正在運行的線程在退出前。

+0

這正是我最終做的。我的印象是,只要程序中存在活動線程(state = RUNNABLE而不是TERMINATED),它就會繼續運行。感謝你的回答! – 2014-09-04 17:11:01