多線程的創建方式,常用線程池及7大核心參數

一.多線程創建方式

1.繼承thread類

//繼承Thread類來創建線程
public class ThreadTest {
 
    public static void main(String[] args) {
        //設置線程名字
        Thread.currentThread().setName("thread");
        MyThread myThread = new MyThread();
        myThread.setName("子線程:");
        //開啓線程
        myThread.start();
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
}
 
class MyThread extends Thread{
    //重寫run()方法
    public void run(){
        for(int i=0;i<10; i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
}

2.實現Runable接口

//實現Runnable接口
public class RunnableTest {
  
    public static void main(String[] args) {
        //設置線程名字
        Thread.currentThread().setName("thread:");
        Thread thread = new Thread(new MyRunnable());
        thread.setName("子線程:");
        //開啓線程
        thread.start();
        for(int i=0; i<10;i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
}
  
class MyRunnable implements Runnable {
  
    @Override
    public void run() {
        for (int i=0; i<10; i++) {
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
}

3.實現Callable接口(有回調)

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
//實現Callable接口
public class CallableTest {
 
    public static void main(String[] args) {
        //執行Callable 方式,需要FutureTask 實現實現,用於接收運算結果
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyCallable());
        new Thread(futureTask).start();
        //接收線程運算後的結果
        try {
            Integer sum = futureTask.get();
            System.out.println(sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
 
class MyCallable implements Callable<Integer> {
 
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i=0; i<10; i++) {
            sum += i;
        }
        return sum;
    }
}

4.線程池創建

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//線程池實現
public class ThreadPoolExecutorTest {
 
    public static void main(String[] args) {
        //創建線程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        ThreadPool threadPool = new ThreadPool();
        for(int i =0;i<5;i++){
            //爲線程池分配任務
            executorService.submit(threadPool);
        }
        //關閉線程池
        executorService.shutdown();
    }
}
 
class ThreadPool implements Runnable {
 
    @Override
    public void run() {
        for(int i=0 ;i<10;i++){
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }

}

二.常用線程池

1.newFixedThreadPool
創建一個指定工作線程數量的線程池。每當提交一個任務就創建一個工作線程,如果工作線程數量達到線程池初始的最大數,則將提交的任務存入到池隊列中。

newFixedThreadPool是一個典型且優秀的線程池,它具有線程池提高程序效率和節省創建線程時所耗的開銷的優點。但是,在線程池空閒時,即線程池中沒有可運行任務時,它不會釋放工作線程,還會佔用一定的系統資源。

2.newCachedThreadPool
創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。

這種類型的線程池特點是:
(1)工作線程的創建數量幾乎沒有限制(其實也有限制的,數目爲Interger. MAX_VALUE), 這樣可靈活的往線程池中添加線程。
如果長時間沒有往線程池中提交任務,即如果工作線程空閒了指定的時間(默認爲1分鐘),則該工作線程將自動終止。終止後,如果你又提交了新的任務,則線程池重新創建一個工作線程。
(2)在使用newCachedThreadPool時,一定要注意控制任務的數量,否則,由於大量線程同時運行,很有會造成系統癱瘓。

3.newSingleThreadExecutor
創建一個單線程化的Executor,即只創建唯一的工作者線程來執行任務,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO,優先級)執行。如果這個線程異常結束,會有另一個取代它,保證順序執行。單工作線程最大的特點是可保證順序地執行各個任務,並且在任意給定的時間不會有多個線程是活動的。

4.newScheduleThreadPool
創建一個定長的線程池,而且支持定時的以及週期性的任務執行,支持定時及週期性任務執行。

 

三.線程池七大核心參數

1.corePoolSize(核心線程數)

2.maxPoolSize(最大線程數)

3.keepAliveTime(空閒回收時間)

4.unit(回收時間單位)

5.workQueue(任務隊列)

6.threadFactory(線程工廠,用於創建線程,一般爲默認線程工廠即可)

7.handler(拒絕策略)

 

當調用 execute(()方法添加一個請求任務時,線程池會做如下判斷:

當創建線程任務數小於核心線程數corePoolSize時則直接創建執行,當創建線程任務數大於核心線程數時則加入任務隊列workQueue中

(常用的任務隊列有 有界隊列1.ArrayBlockingQueue,2.SynchronousQueue,

無界隊列:1.LinkedBlockingQueue,暫不詳述。)等待,

當任務隊列也放滿之後查看是否大於最大線程數maxPoolSize,如果這時候隊列滿了且正在運行的線程數量還小於 naximumPoolSize,,那麼還是要創建非核心線程立刻運行這個任務,如果大於最大線程數則執行拒絕策略handler

(拒絕策略有分爲四種:

1. CallerRunsPolicy :這個策略重試添加當前的任務,他會自動重複調用 execute() 方法,直到成功。

2. AbortPolicy :對拒絕任務拋棄處理,並且拋出異常。

3. DiscardPolicy :對拒絕任務直接無聲拋棄,沒有異常信息。

4. DiscardOldestPolicy :對拒絕任務不拋棄,而是拋棄隊列裏面等待最久的一個線程,然後把拒絕任務加到隊列。

)如果沒有則創建執行。當一個線程完成任務時,它會從隊列中取下一個任務來執行。當一個線程無事可做超過一定的時間( keepAliveTime))時,線程池會判斷:如果當前運行的線程數大於 corePoolSize,,那麼這個線程就被停掉。所以線程池的所有任務完成後它最終會收縮到 corePoolSize的大小。

​​​​​​​

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章