Java Thread - 控制你的线程

本人博客已经迁移至 www.shangyang.me 欢迎大家访问

 

1. Introduction

 

为了不让系统overloaded, 通常你不但需要创建线程,同时你也需要控制你的线程数量.

 

2. 方案

 

    总体的规划是, 线程执行的过程中不超过一定临界值_latch。 如果超过了这个数量,那么会严重影响我的系统系能,甚至crash.

 

    2.1 方案1 - 利用 CountDownLatch

 

          CountDownLatch 的特性是,定义一个Latch值,  创建你的Threads, 如果你的数量不够这个 Latch值,CoundDownLatch 不会自动打开,执行你的线程. 一旦你的Threads 达到了 Latch 值,那么这些线程会一窝蜂的同时执行 ( 如果要测试 并发性,这个是个不错的选择 )。

 

          该方案可以很好的控制我的线程数量在一个数量级,但是,这个并不是我的最优方案.

 

          1. 线程 在达到 Latch 之前,都是阻塞住的。并不能让线程一直执行。
              我的期望是,Threads可以自由的创建并执行,"只是当前同步线程达到 了_latch时,不允许新的线程继续创建,必须等待正在执行的线程结束以后,当前线程数量小于该临界值_latch后,允许新的线程创建并且执行"。

 

    2.2 方案2 - 同步的线程不能超过临界值latch,但只要低于该latch, 线程都可以只有的创建和执行.

 

          这种情况下,CountDownLatch 不能完全满足我们的要求,我们只能定义自己的 ThreadMonitor.

 

          设计时序图:

import java.util.concurrent.CountDownLatch;

import org.junit.Test;

/**
 * 
 * Prototype to monitor the concurrence threads.
 * 
 * Design:
 * 		 Key:
 * 			 _latch: to limit the number of the current threads that running concurrence.
 * 		  
 * 		 Scenario:
 *   			    1. If the current threads number not exceeds the _latch, initialize the threads and let them to start immediately.
 * 		 			2. If the current threads number equals the _latch, all the other threads need to wait.
 * 		 So this will guarantee that our system would be always less or equal than the _latch number of current threads executing at the same time to 
 * 		 efficiently control our system not overloaded.
 * 
 * @see java.util.concurrence.CountDownLatch to see how control the Latch.
 * 
 * 
 * @author shangyang
 *
 */
public class ThreadControlTest {
	
	@Test
	public void threadControlTest() throws InterruptedException{
		
		ThreadMonitor monitor = new ThreadMonitor();
		
		for(int i=0; i<100; i++){
			
			MockThread thread = new MockThread(monitor);
			// Increase the static _currentThreadNum of the ThreadMonitor .
			monitor.increase();
			
			thread.start();
			/*
			 * If the _currentThreadNum exceeds/equals the _latch, main thread should be hanging on until  the _currentThreadNum reduce to 
			 * the num lower than _latch. So this would guarantee that there would be always no more than _latch threads concurrence.
			 */
			monitor.control();
			
			System.out.println("i=" + i);
		}
	}
	
}

/**
 * 
 * The monitor class to maintain the concurrence threads.
 * 
 * @author shang yang
 *
 */
class ThreadMonitor{
	
	public static int _currentConcurThreadsNum = 0; // represents how many threads running currently.
	
	final static int _latch = 5;
	
	boolean _isMainThreadAwaited = false;
	
	CountDownLatch _downLatch = null;
	
	/**
	 * If the _currentThreadsNum exceeds the _latch, hanging on the current main thread. ( @see java.util.concurrence.CountDownLatch )
	 * It can not be made as synchronized, because it was used to hang on the main thread. see the scenarios below,
	 * If we added the synchronized, what the consequence it is:
	 * 1. The main thread is awaiting in controller() method. see _downLatch.await()
	 *    1.1 Because the controller() method is synchronized, and main thread owned the lock of the Object "ThreadMonitor"
	 *    1.2 That means, it will also locked the synchronized method increase() and countDown(), 
	 *    	  which means the other threads are also can not access the 2 methods
	 * 2. If #1 happened, we need the thread to execute the countDown(), and open the Latch to wake up the main thread
	 *    But of the reason of #1.1 and #1.2, the lock of the Object "ThreadMonitor" has been owned by the main thread and can not release it
	 *    So the thread can not invoke the ThreadMonitor.countDown() and always be waiting the main thread to release the Object lock.
	 *    
	 * Finally, we will see that the main process is hanging on always cause 
	 * 	   1. Main Thread waiting for the thread to countDown() to open the latch
	 * 	   2. The Thread waiting for the main Thread to release the lock on the control() method.
	 * 	-->  The two are always waiting with each other all the time.    
	 * 
	 * 
	 * 
	 * @throws InterruptedException
	 */
	public void control() throws InterruptedException{
		
		/*
		 *
		 */
			if( _currentConcurThreadsNum >= _latch  ){
				
				_downLatch = new CountDownLatch(1);
				
				System.err.println("_currentConcurThreadsNum:"+_currentConcurThreadsNum+"; Exceeds the _latch, main thread hanging on, not allow any more threads initialization");
				_isMainThreadAwaited = true;
				
				_downLatch.await();		// let the main thread to wait.	
			}
	}
	
	/**
	 * if a new threads initialized, increase it.
	 * 
	 * synchronized added here for the reason that _currentConcurThreadsNum is concurrence access.
	 */
	public synchronized void increase(){
			_currentConcurThreadsNum ++;
			System.out.println("_currentConcurThreadsNum is increased to:" + _currentConcurThreadsNum);
	}
	
	/**
	 * If a thread completed, count down the _currentThreadsNum. and more, if the _currentThreadsNum < _latch, we should open the _latch and let the main thread 
	 * to continuous processing.
	 */
	public synchronized void countDown(){
		_currentConcurThreadsNum --;
		System.out.println("_currentConcurThreadsNum is reduced to:" + _currentConcurThreadsNum);
		
		if ( _currentConcurThreadsNum < _latch ){
			
			if(_isMainThreadAwaited){
				
				_downLatch.countDown();
				_isMainThreadAwaited = false;
				
				System.err.println("now the _currentConcurThreadsNum:"+_currentConcurThreadsNum+"; Down the _latch, Latch open, allow "+ ( _latch-_currentConcurThreadsNum ) + " threads initialization ");
			
			}
		} 
		
	}

}

class MockThread extends Thread{
	ThreadMonitor _monitor;
	
	public MockThread(ThreadMonitor monitor){
		_monitor = monitor;
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
			// waiting here and reduce 1 for the COUNT_LATCH num. 
			// Until COUNT_LATCH has reduce to 0, continue.
			System.out.println("Thread running~~~");	
			
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			_monitor.countDown();
			
			System.out.println("Thread ended~~");
	}
	
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值