Java線程池實現原理之自定義線程池(一)


1.隊列的概念

談到多線程先講下隊列的概念,之后的多線程學習會用到此類知識。

隊列分為:阻塞式隊列(有界)、非阻塞式隊列(無界),遵循着先進先出、后進后出的原則。
阻塞隊列與非阻塞隊列區別:
1.非阻塞式隊列超出隊列總數會丟失。
2.阻塞式隊列超出總數會進入等待(等待時間=設置超時時間)。
3.獲取隊列方面:非阻塞式隊列,如果為空返回null。阻塞式隊列,如果為空也會進入等待。

非阻塞式隊列ConcurrentLinkedDeque
 
        
 1 //非阻塞式隊列 無界(可以聲明無限個隊列)
 2     public static void test1(){  3 
 4         ConcurrentLinkedDeque<Object> objects = new ConcurrentLinkedDeque<>();  5         objects.offer("java001");  6         objects.offer("java002");  7 
 8         System.out.println("隊列總數:"+objects.size());  9 
10         //建議:獲取隊列之后刪除
11         System.out.println("獲取隊列但不刪除:"+objects.peek()); 12         System.out.println("獲取隊列但不刪除,隊列總數:"+objects.size()); 13         System.out.println("獲取隊列刪除:"+objects.poll()); 14 
15         //非阻塞式隊列,如果為空返回null
16  System.out.println(objects.poll()); 17  System.out.println(objects.poll()); 18  System.out.println(objects.poll()); 19         System.out.println("獲取隊列刪除,隊列總數:"+objects.size()); 20     }
 
        

 

 
        
阻塞式隊列ArrayBlockingQueue
 
        
 1 //阻塞式隊列
 2     public static void test2() throws InterruptedException {  3 
 4         long startTime=System.currentTimeMillis();  5         ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(3);  6         arrayBlockingQueue.offer("A001",3, TimeUnit.SECONDS);  7         arrayBlockingQueue.offer("A002",3, TimeUnit.SECONDS);  8 
 9         //阻塞式隊列超出總數等待(等待時間=設置超時時間)
10         arrayBlockingQueue.offer("A003",3, TimeUnit.SECONDS); 11         arrayBlockingQueue.offer("A004",1, TimeUnit.SECONDS); 12         arrayBlockingQueue.offer("A005",1, TimeUnit.SECONDS); 13 
14         System.out.println("隊列總數:"+arrayBlockingQueue.size()); 15  System.out.println(arrayBlockingQueue.poll()); 16  System.out.println(arrayBlockingQueue.poll()); 17  System.out.println(arrayBlockingQueue.poll()); 18         //阻塞式隊列,如果為空也會等待。
19         System.out.println(arrayBlockingQueue.poll(1, TimeUnit.SECONDS)); 20         System.out.println("隊列剩余總數:"+arrayBlockingQueue.size()); 21 
22         System.out.println("耗時:"+ (System.currentTimeMillis() - startTime)/1000 +"秒"); 23 
24     }
 
        

2.線程池

 
        
線程池好處:
1.降低資源 => 重復利用機制 (降低創建線程和銷毀線程)
2.提高響應效率 => 當任務到達時,任務可以不需要等待去創建線程就可以執行
3.方便管理 => 無限創建線程消耗資源、降低系統穩定性。使用線程池可以統一分配、調優、監控。
線程與任務的區別:
可以把線程理解成一個工作人員。而任務就是這個工作人員干的活。比如,餐廳的工作人員在為顧客傳菜,傳菜就是個任務。

Java中線程就是Thread類或其子類的一個實例。
也就是說你不必關注線程對象是用哪種方法創建的。在此基礎上,線程所執行的代碼,即run方法中的代碼所實現的處理邏輯,
比如讀取數據庫中的一條記錄,就是一個任務。因此,所謂任務是一個相對的概念。一個任務可以是讀取數據庫中的一條記錄,
也可以是FTP傳輸一批文件,FTP傳輸一個文件……
 
        
 1 //創建線程四種方式:  2     //1.可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。  3     //2.定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。  4     //3.可定時線程池,支持定時及周期性任務執行。  5     //4.單例線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
 6     public static void test1() {  7 
 8         //1.可緩存、定時、定長、單例
 9         ExecutorService executorService = Executors.newCachedThreadPool(); 10         for (int i = 0; i <10 ; i++) { 11             final int i1 = i; 12             executorService.execute(new Runnable() { 13  @Override 14                 public void run() { 15                     System.out.println(Thread.currentThread().getName()+",i:"+ i1); 16  } 17  }); 18  } 19 
20  } 21 
22     public static void test2() { 23 
24         //2.可定長線程,核心線程5個,最多創建5個線程 (只會創建5個線程,其他線程共享這5個線程)
25         ExecutorService executorService = Executors.newFixedThreadPool(5); 26         for (int i = 0; i <10 ; i++) { 27             final int i1 = i; 28             executorService.execute(new Runnable() { 29  @Override 30                 public void run() { 31                     System.out.println(Thread.currentThread().getName()+",i:"+ i1); 32  } 33  }); 34  } 35  } 36 
37     public static void test3() { 38 
39         long l = System.currentTimeMillis(); 40         //3.可定時線程 =>核心線程數3 (延遲三秒執行)
41         ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3); 42         for (int i = 0; i <10 ; i++) { 43 
44             final int i1 = i; 45             scheduledExecutorService.schedule(new Runnable() { 46  @Override 47                 public void run() { 48                     System.out.println(Thread.currentThread().getName()+",i:"+ i1); 49                     System.out.println("耗時:"+ (System.currentTimeMillis() -l)/1000 +"秒" ); 50  } 51             },3, TimeUnit.SECONDS); 52  } 53 
54 
55 
56  } 57 
58     public static void test4() { 59 
60         //4.單例線程 =>核心線程數1 最大線程數1
61         ExecutorService executorService = Executors.newSingleThreadExecutor(); 62         for (int i = 0; i <10 ; i++) { 63             final int i1 = i; 64             executorService.execute(new Runnable() { 65  @Override 66                 public void run() { 67                     System.out.println(Thread.currentThread().getName()+",i:"+ i1); 68  } 69  }); 70  } 71     }
 
         
         
        

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM