java 創建線程池的4中方式
線程池的作用:
線程池作用就是限制系統中執行線程的數量。
根據系統的環境情況,可以自動或手動設置線程數量,達到運行的最佳效果;少了浪費了系統資源,多了造成系統擁擠效率不高。用線程池控制線程數量,其他線程排隊等候。一個任務執行完畢,再從隊列的中取最前面的任務開始執行。若隊列中沒有等待進程,線程池的這一資源處於等待。當一個新任務需要運行時,如果線程池中有等待的工作線程,就可以開始運行了;否則進入等待隊列。
java中常用線程池
- newSingleThreadExecutor
創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當於單線程串行執行所有任務。如果這個唯一的線程因為異常結束,那麽會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。
創建固定大小的線程池。每次提交一個任務就從線程池中拿一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那麽線程池會補充一個新線程。- newCachedThreadPool
創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,
那麽就會回收部分空閑(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小。
4.newScheduledThreadPool
創建一個支持定時以及周期性執行任務的線程池。多數情況下可用來替代Timer類
- newCachedThreadPool
單線程線程池 Executors.newSingleThreadExecutor()
import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Chi { public static void main(String[] args) { /*沒有線程池的寫法 Runnable r = new MyRunnable(); Thread t = new Thread(r); t.start();*/ ExecutorService e =Executors.newSingleThreadExecutor();//創建一個單線程的線程池 e.submit(new MyRunnable()); e.submit(new MyRunnable()); e.submit(new MyRunnable()); e.submit(new MyRunnable()); e.submit(new MyRunnable()); e.submit(new MyRunnable()); e.shutdown(); } } class MyRunnable implements Runnable{ @Override public void run() { System.out.println("給我一個線程:"+Thread.currentThread().getName()); try { System.out.println("線程開始消耗資源"+Thread.currentThread().getName()); Thread.sleep(2000); System.out.println("線程使用完畢"+Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("歸還到線程池中"+Thread.currentThread().getName()); } }
運行結果
給我一個線程:pool-1-thread-1
線程開始消耗資源pool-1-thread-1
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
給我一個線程:pool-1-thread-1
線程開始消耗資源pool-1-thread-1
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
給我一個線程:pool-1-thread-1
線程開始消耗資源pool-1-thread-1
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
給我一個線程:pool-1-thread-1
線程開始消耗資源pool-1-thread-1
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
給我一個線程:pool-1-thread-1
線程開始消耗資源pool-1-thread-1
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
給我一個線程:pool-1-thread-1
線程開始消耗資源pool-1-thread-1
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
創建一個固定長度的線程池 Executors.newFixedThreadPool()
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Chi {
public static void main(String[] args) {
/*沒有線程池的寫法
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();*/
ExecutorService e =Executors.newFixedThreadPool(2);//創建一個包含兩個線程的線程池
Runnable r = new MyRunnable();
e.submit(r);//獲取線程池中的某一個線程對象,然後調用runnable接口中的run方法
e.submit(r);
e.submit(r);
e.submit(r);//註意run方法運行完,線程中的線程並不消耗,而是歸還到池中
e.shutdown();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("給我一個線程:"+Thread.currentThread().getName());
try {
System.out.println("線程開始消耗資源"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("線程使用完畢"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("歸還到線程池中"+Thread.currentThread().getName());
}
}
運行結果
給我一個線程:pool-1-thread-1
給我一個線程:pool-1-thread-2
線程開始消耗資源pool-1-thread-1
線程開始消耗資源pool-1-thread-2
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
線程使用完畢pool-1-thread-2
給我一個線程:pool-1-thread-1
線程開始消耗資源pool-1-thread-1
歸還到線程池中pool-1-thread-2
給我一個線程:pool-1-thread-2
線程開始消耗資源pool-1-thread-2
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-1
線程使用完畢pool-1-thread-2
歸還到線程池中pool-1-thread-2
創建一個可緩存的線程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Chi {
public static void main(String[] args) {
/*沒有線程池的寫法
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();*/
ExecutorService e =Executors.newCachedThreadPool();
Runnable r = new MyRunnable();
e.submit(r);//獲取線程池中的某一個線程對象,然後調用runnable接口中的run方法
e.submit(r);
e.submit(r);
e.submit(r);//註意run方法運行完,線程中的線程並不消耗,而是歸還到池中
e.shutdown();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("給我一個線程:"+Thread.currentThread().getName());
try {
System.out.println("線程開始消耗資源"+Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("線程使用完畢"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("歸還到線程池中"+Thread.currentThread().getName());
}
}
運行結果
給我一個線程:pool-1-thread-1
給我一個線程:pool-1-thread-4
給我一個線程:pool-1-thread-3
給我一個線程:pool-1-thread-2
線程開始消耗資源pool-1-thread-3
線程開始消耗資源pool-1-thread-4
線程開始消耗資源pool-1-thread-1
線程開始消耗資源pool-1-thread-2
線程使用完畢pool-1-thread-2
線程使用完畢pool-1-thread-3
線程使用完畢pool-1-thread-4
線程使用完畢pool-1-thread-1
歸還到線程池中pool-1-thread-4
歸還到線程池中pool-1-thread-2
歸還到線程池中pool-1-thread-3
歸還到線程池中pool-1-thread-1
創建一個可緩存並且可以周期性執行任務的線程池
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Chi {
public static void main(String[] args) {
/*沒有線程池的寫法
Runnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();*/
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ScheduledThreadPoolExecutor e = new ScheduledThreadPoolExecutor(3);//參數表示線程容量
System.out.println(simpleDateFormat.format(new Date()));
// 但是如果執行任務時間大約2s則不會並發執行後續任務將會延遲。
ScheduledFuture<?> resultFuture = e.scheduleAtFixedRate(new MyRunnable(), 0, 2000, TimeUnit.MILLISECONDS);//第一個參數任務,第二個參數表示執行任務前等待的時間,第三個參數表示任務啟動間隔時間,第四參數表示時間單位
e.scheduleAtFixedRate(new MyRunnable1(), 0, 2000, TimeUnit.MILLISECONDS);//第一個參數任務,第二個參數表示執行任務前等待的時間,第三個參數表示任務啟動間隔時間,第四參數表示時間單位
// // 由於是定時任務,一直不會返回
//Object object = resultFuture.get();
}
}
class MyRunnable implements Runnable{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"給我一個線程:"+simpleDateFormat.format(new Date()));
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyRunnable1 implements Runnable{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"給我一個線程1:"+simpleDateFormat.format(new Date()));
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
運行結果
2018-03-17 13:48:05
pool-1-thread-1給我一個線程:2018-03-17 13:48:05
pool-1-thread-2給我一個線程1:2018-03-17 13:48:05
pool-1-thread-1給我一個線程:2018-03-17 13:48:07
pool-1-thread-1給我一個線程:2018-03-17 13:48:09
pool-1-thread-3給我一個線程:2018-03-17 13:48:11
pool-1-thread-3給我一個線程:2018-03-17 13:48:13
pool-1-thread-2給我一個線程1:2018-03-17 13:48:15
pool-1-thread-3給我一個線程:2018-03-17 13:48:15
pool-1-thread-3給我一個線程:2018-03-17 13:48:17
pool-1-thread-3給我一個線程:2018-03-17 13:48:19
pool-1-thread-1給我一個線程:2018-03-17 13:48:21
pool-1-thread-1給我一個線程:2018-03-17 13:48:23
pool-1-thread-3給我一個線程1:2018-03-17 13:48:25
pool-1-thread-1給我一個線程:2018-03-17 13:48:25
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
java 創建線程池的4中方式