Java中怎么控制線程訪問資源的數量

jopen 10年前發布 | 30K 次閱讀 Java Java開發

在API中是這樣來描述Semaphore 的

Semaphore 通常用于限制可以訪問某些資源(物理或邏輯的)的線程數目。

一個計數信號量。從概念上講,信號量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然后再獲取該許可。每個release() 添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可對象,Semaphore 只對可用許可的號碼進行計數,并采取相應的行動。

 

例如,下面的類使用信號量控制線程并發的數量
    import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class TestSemaphore {  

    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
         ExecutorService pool =  Executors.newCachedThreadPool();  
         final Semaphore sp = new Semaphore(3,true);  
         for(int i=0;i<10;i++){  
             Runnable runnable = new Runnable() {  

                @Override  
                public void run() {  

                       try {  
                        sp.acquire();  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                   }  
                       System.out.println(sp.availablePermits());  
                   System.out.println("線程  "+ Thread.currentThread().getName() +"進入,已有"+ (3-sp.availablePermits())+ "并發") ;  
                   try {  
                    Thread.sleep((long) (Math.random()*3000));  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
                   System.out.println("線程  "+Thread.currentThread().getName() +"即將離開 " );  
                   sp.release();  
                   System.out.println("線程  "+Thread.currentThread().getName() +"離開 ,已有"+ (3-sp.availablePermits()) + "并發");  
                }  
            };  
            pool.execute(runnable);  
         }  
    }  

}  </pre> 再例如可以通過信號量來控制線程訪問資源:<pre class="brush:java; toolbar: true; auto-links: false;">    import java.util.concurrent.Semaphore;  


public class DownloadThread {  
    private static int in_index = 0;  
    private static int out_index = 0;  
    private static int buffer_count = 100;  
    public static boolean g_downloadComplete;  
    private static Semaphore g_seFull = new Semaphore(0);  
    private static Semaphore g_seEmpty = new Semaphore(buffer_count);  
     public static boolean getBlockFromNet(int in_index) {  
          int i = 0;  
          while (i < 10000)  
           i++;  
          if (in_index < buffer_count - 1)  
           return false;  
          else  
           return true;  
         }  
         public static void writeBlockToDisk(int out_index) {  
          int i = 0;  
          while (i < 100000)  
           i++;  
         }  

    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
         g_downloadComplete = false;  
          Thread threadA = new Thread() {  
           public void run() {  
            proA();  
           }  
          };  
          Thread threadB = new Thread() {  
           public void run() {  
            proB();  
           }  
          };  
          threadB.start();  
          threadA.start();  
         }  



    public static void proA(){  
         while (g_seFull.availablePermits() < buffer_count) {  
               try {  
                g_seEmpty.acquire();  
               } catch (InterruptedException e1) {  
                // TODO Auto-generated catch block  
                e1.printStackTrace();  
               }  
               g_downloadComplete = getBlockFromNet(in_index);  
               in_index = (in_index + 1) % buffer_count;  
               g_seFull.release();  
               System.out.println("download a block " + in_index);  
               if (g_downloadComplete)  
                break;  
              }  
    }  

    public static void proB(){  
         while (g_seEmpty.availablePermits() > 0) {  
               try {  
                g_seFull.acquire();  
               } catch (InterruptedException e1) {  
                // TODO Auto-generated catch block  
                e1.printStackTrace();  
               }  
               writeBlockToDisk(out_index);  
               out_index = (out_index + 1) % buffer_count;  
               g_seEmpty.release();  
               System.out.println("write a block " + out_index);  
               if (g_downloadComplete && out_index == in_index)  
                break;  
              }  
    }  

}  </pre>
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!