google-code-prettify

2015年1月23日 星期五

簡易限制同時多執行緒數量Simple Limited Concurrent Multi-thread

因為工作常需要處理較大數量的資料,
使用單執行緒耗時較久,
所以就想寫一個多執行緒的程序來做,
但不能無限制的往Server丟,
Server恐怕也會吃不消,
所以必須控制同時多執行緒執行的數量。
另外,也為了要考量到原本已寫好的Service必須可以直接使用,
套用多執行緒後不用改Code,
保持需要時,原本只有主執行緒運算的狀況下仍可進行,
所以就利用時間寫了以下這樣一個簡易可以指定同時間多執行緒數量的程式,
並且這個控制同時執行緒數量的框架架構可以在後來其他新的程式工作直接套用即可,
不需再寫產生多執行緒、控制Concurrent Multi-thread的程式。
 
<span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">interface</span><span class="pln"> </span><span class="typ">BatchService</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
 </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Collection</span><span class="pun">&lt;!----&gt;</span><span class="pln"> retrieveSource</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">throws</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">;</span><span class="pln">
 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> doJob</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Object</span><span class="pln"> obj </span><span class="pun">)</span><span class="pln"> </span><span class="kwd">throws</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span>

 
public interface Job extends Runnable {
 public void setData(Object obj);
 public void setService(BatchService service);
}

 
public class JobImpl implements Job {

 //private static Logger log = Logger.getLogger(JobImpl.class);
 
 private Object data;
 private BatchService service;
 
 @Override
 public void run() {
  Thread.currentThread().setName(Thread.currentThread().getId()+"");
  if (data == null || service == null) return;
  
  try {
   service.doJob(data);
   this.setData(null);
   this.setService(null);
   
   
  } catch (Exception e) {
   e.printStackTrace();
   //System.out.println(e.getMessage());
   //log.error(e.getMessage());
   
  }finally{
   BatchInit.infoJobFinishCount(this);
  }
 }

 @Override
 public void setData(Object obj) {
  data = obj;
  
 }

 @Override
 public void setService(BatchService service) {
  this.service = service;
 }

}

 
<span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BatchInit</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
 </span><span class="com">//private static Logger log = LogManager.getLogger("BatchInit");</span><span class="pln">
 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Stack</span><span class="str">&lt;job&gt;</span><span class="pln"> jobStack</span><span class="pun">;</span><span class="pln">

 </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> </span><span class="typ">JobFinishCount</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

 
 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> batchJob</span><span class="pun">(</span><span class="typ">BatchService</span><span class="pln"> batchService</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Stack</span><span class="str">&lt;job&gt;</span><span class="pln"> jobs</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">throws</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">{</span><span class="pln">
  </span><span class="typ">List</span><span class="pun">&lt;!----&gt;</span><span class="pln"> source </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">List</span><span class="pun">&lt;!----&gt;)</span><span class="pln">batchService</span><span class="pun">.</span><span class="pln">retrieveSource</span><span class="pun">()</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> </span><span class="typ">JobAmount</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> source</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln">
  jobStack </span><span class="pun">=</span><span class="pln"> jobs</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">int</span><span class="pln"> </span><span class="typ">JobNow</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="com">//log.info("JobAmount::"+JobAmount);</span><span class="pln">
  
  </span><span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">){</span><span class="pln">
   </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">JobAmount</span><span class="pun">==</span><span class="typ">JobFinishCount</span><span class="pun">){</span><span class="pln">
    </span><span class="com">//System.out.println("做完了::"+JobFinishCount);</span><span class="pln">
    </span><span class="com">//log.info("做完了::"+JobFinishCount);</span><span class="pln">
    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   </span><span class="typ">Job</span><span class="pln"> job </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">try</span><span class="pun">{</span><span class="pln">
    job </span><span class="pun">=</span><span class="pln"> jobStack</span><span class="pun">.</span><span class="pln">pop</span><span class="pun">();</span><span class="pln">
    
   </span><span class="pun">}</span><span class="kwd">catch</span><span class="pun">(</span><span class="pln">java</span><span class="pun">.</span><span class="pln">util</span><span class="pun">.</span><span class="typ">EmptyStackException</span><span class="pln"> ex</span><span class="pun">){</span><span class="pln">
  
   </span><span class="pun">}</span><span class="kwd">catch</span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> ex</span><span class="pun">){</span><span class="pln">
    ex</span><span class="pun">.</span><span class="pln">printStackTrace</span><span class="pun">();</span><span class="pln">
    </span><span class="com">//log.error(ex.getMessage());</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   
   </span><span class="com">//log.debug("#######job ::"+job);</span><span class="pln">
   </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">job </span><span class="pun">!=</span><span class="pln"> </span><span class="kwd">null</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="typ">JobNow</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">JobAmount</span><span class="pln"> </span><span class="pun">){</span><span class="pln">
    loga</span><span class="pun">(</span><span class="typ">JobFinishCount</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Object</span><span class="pln"> obj </span><span class="pun">=</span><span class="pln"> source</span><span class="pun">.</span><span class="kwd">get</span><span class="pun">(</span><span class="typ">JobNow</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">++</span><span class="typ">JobNow</span><span class="pun">;</span><span class="pln">
    job</span><span class="pun">.</span><span class="pln">setData</span><span class="pun">(</span><span class="pln">obj</span><span class="pun">);</span><span class="pln">
    job</span><span class="pun">.</span><span class="pln">setService</span><span class="pun">(</span><span class="pln">batchService</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">Thread</span><span class="pln"> t </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">(</span><span class="pln">job</span><span class="pun">,</span><span class="pln"> job</span><span class="pun">.</span><span class="pln">toString</span><span class="pun">());</span><span class="pln">
    t</span><span class="pun">.</span><span class="pln">start</span><span class="pun">();</span><span class="pln">
    
   </span><span class="pun">}</span><span class="pln">
   
  </span><span class="pun">}</span><span class="pln">
  
 </span><span class="pun">}</span><span class="pln">

 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">synchronized</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> infoJobFinishCount</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Job</span><span class="pln"> job</span><span class="pun">){</span><span class="pln">
  </span><span class="pun">++</span><span class="typ">JobFinishCount</span><span class="pun">;</span><span class="pln">
  jobStack</span><span class="pun">.</span><span class="pln">push</span><span class="pun">(</span><span class="pln">job</span><span class="pun">);</span><span class="pln">
  
 </span><span class="pun">}</span><span class="pln">
 
 </span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> loga</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> </span><span class="typ">String</span><span class="pln"> message</span><span class="pun">){</span><span class="pln">
  </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">%</span><span class="pln"> </span><span class="lit">500</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">){</span><span class="pln">
   </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"--doing :"</span><span class="pln"> </span><span class="pun">+</span><span class="pln">i</span><span class="pun">+</span><span class="str">", "</span><span class="pun">+</span><span class="pln">message</span><span class="pun">);</span><span class="pln">
   </span><span class="com">//log.info("--doing :" +i+", "+message);</span><span class="pln">

  </span><span class="pun">}</span><span class="pln">
 </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span>

上面的程式是控制同一時間執行緒的最大數量,之後不用在改(除非有Bug,或為了提升效率),
以後新的需要多執行緒進行的程式可以直接引用。
而下面的兩隻程式必須要寫,
一個是實作每一個Batch Job Service的實際工作必須implements BatchService這個interface,
另一個則是啟動程式和同一時間處理Job數量(執行緒數量)設定
 
<span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyBatchJobService</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">BatchService</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

 </span><span class="lit">@Override</span><span class="pln">
 </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Collection</span><span class="pun">&lt;!----&gt;</span><span class="pln"> retrieveSource</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">throws</span><span class="pln"> </span><span class="typ">Exception</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">//TODO write your code</span><span class="pln">
  </span><span class="typ">ArrayList</span><span class="pun">&lt;</span><span class="typ">String</span><span class="pun">&gt;</span><span class="pln"> source </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArrayList</span><span class="pun">&lt;</span><span class="typ">String</span><span class="pun">&gt;();</span><span class="pln">
  source</span><span class="pun">.</span><span class="kwd">add</span><span class="pun">(</span><span class="str">"Hello "</span><span class="pun">);</span><span class="pln">
  source</span><span class="pun">.</span><span class="kwd">add</span><span class="pun">(</span><span class="str">"Ryan! "</span><span class="pun">);</span><span class="pln">
  source</span><span class="pun">.</span><span class="kwd">add</span><span class="pun">(</span><span class="str">"How "</span><span class="pun">);</span><span class="pln">
  source</span><span class="pun">.</span><span class="kwd">add</span><span class="pun">(</span><span class="str">"are "</span><span class="pun">);</span><span class="pln">
  source</span><span class="pun">.</span><span class="kwd">add</span><span class="pun">(</span><span class="str">"you? "</span><span class="pun">);</span><span class="pln">
  
  </span><span class="kwd">for</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++){</span><span class="pln">
   source</span><span class="pun">.</span><span class="kwd">add</span><span class="pun">(</span><span class="str">""</span><span class="pun">+</span><span class="pln">i</span><span class="pun">);</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> source</span><span class="pun">;</span><span class="pln">
 </span><span class="pun">}</span><span class="pln">

 </span><span class="lit">@Override</span><span class="pln">
 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> doJob</span><span class="pun">(</span><span class="typ">Object</span><span class="pln"> obj</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">throws</span><span class="pln"> </span><span class="typ">Exception</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="com">//TODO write your code </span><span class="pln">
  </span><span class="typ">String</span><span class="pln"> data </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="typ">String</span><span class="pun">)</span><span class="pln"> obj</span><span class="pun">;</span><span class="pln">
  </span><span class="typ">System</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"ThreadId:"</span><span class="pun">+</span><span class="pln"> </span><span class="typ">Thread</span><span class="pun">.</span><span class="pln">currentThread</span><span class="pun">().</span><span class="pln">getId</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="str">"::"</span><span class="pun">+</span><span class="pln">data</span><span class="pun">);</span><span class="pln">
 </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">
</span>

執行BatchStart啟動程式。
 
public class BatchStart {

 private static BatchInit batchInit = new BatchInit();
 
 public static void main(String[] args) throws Exception {
  BatchService service = new MyBatchJobService();
  batchJob(service, 2);
  
 }

 private static void batchJob(BatchService service, int amountThread)
   throws Exception {
  Stack jobs = new Stack();
  
  for(int i =0; i < amountThread; i++){  //TODO Setting the amount of concurrent thread
   jobs.push(new JobImpl());
   
  }
  
  batchInit.batchJob(service, jobs);
 }
}

開放原始碼下載:GitHub

沒有留言:

張貼留言