1. 程式人生 > 其它 >Java執行緒(執行緒池、建立執行緒的第三種方法callable)

Java執行緒(執行緒池、建立執行緒的第三種方法callable)

執行緒池

補充資料:Doug Lea (JCP組織的一人)對執行緒池部分貢獻巨大

 

常用執行緒池的介面和類:

Executor:執行緒池的頂級介面

ExecutorService:執行緒池介面可用submit(Runnable Task)提交任務程式碼。包含:Shutdown;

Shutdownnow等

Executors工廠類:可以通過這一個方法得到一個執行緒池

NewFixedThreadPool(int n Thread):獲取固定數量的執行緒池。引數:指執行緒池中執行緒的數量

NewCacheThreadPool()獲取動態數量的執行緒池,無上限

 

對於ExecutorService:需關注實現類TheadPoolExecutor,SheduledThreadPoolExecutor

Executors:1.建立固定執行緒個數的執行緒池

2.建立快取執行緒池,又任務多少來決定

3.建立單執行緒池

4.建立排程執行緒池  排程:週期、定時執行

 

在API中:

Shutdown:啟動一次順序關閉,執行以前提交的任務,但不接受新任務

ShutDownNow:試圖停止所有正在執行的活動任務,暫停處理正在等待的任務,並返回等待執行的任務列表

 

程式碼示例1 固定執行緒個數:

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

 

public class Demo {

    
public static void main(String[] args) { // 1.建立固定執行緒個數的執行緒池 ExecutorService es=Executors.newFixedThreadPool(4); // 2.提交任務 Runnable run=new Runnable() { private int ticket; @Override public void run() { while (true
) { if (ticket <= 0) { break; } System.out.println(Thread.currentThread().getName() + "賣完第:" + ticket + "張票"); ticket--; } } }; // 3.提交任務 for(int i=0;i<=4;i++) { es.submit(run); } // 4.關閉執行緒池 es.shutdown(); } }

 

 

 

程式碼示例 2 可變執行緒個數,由任務決定

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class Demo {
    public static void main(String[] args) {
//        1.建立固定執行緒個數的執行緒池
//        ExecutorService es=Executors.newFixedThreadPool(4);
        ExecutorService es2=Executors.newCachedThreadPool();
//        2.提交任務
        Runnable run=new Runnable() {
            private int ticket;
 
            @Override
            public void run() {
                while (true) {
                    if (ticket <= 0) {
                        break;
                    }
                    System.out.println(Thread.currentThread().getName() + "賣完第:" + ticket + "張票");
                    ticket--;
                }
            }
        };
//        3.提交任務
                for(int i=0;i<=4;i++) {
            es2.submit(run);
        }
//        4.關閉執行緒池
        es2.shutdown();
        }
}

 

注:提交任務數不一定是4.要具體看執行結果

 

Excutors的另外兩種方法

3. ExecutorService e3=Executors.newSingleThreadExecutor();
4. ExecutorService e4=Executors.newScheduledThreadPool();

 

 

Callable介面

語法:

Public interface Callable<V>{public V call() throws Exception}

特點:有返回值;使用時需要先轉化為任務後被Thread呼叫

 

程式碼示例:

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
 
public class Demo02 {
    public static void main(String[] args) {
//        功能需求:計算1-100的和並使用Callable介面
        Callable<Integer> callable=new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println(Thread.currentThread().getName()+"開始計算");
                int sum = 0;
                for (int j = 1;j<=100;j++){
                    sum+=j;
                    Thread.sleep(100);
                }
                return sum;
 
            }
        };
//        把Callable轉化為可執行的任務
        FutureTask<Integer> task = new FutureTask<>(callable);
 
//        建立執行緒
        Thread thread = new Thread(task);
 
//        啟動執行緒
        thread.start();
 
//        獲取結果
        Integer sum= null;
        try {
            sum = task.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("結果是"+sum);
        }
}

 

 

 

Callable與執行緒池的結合的使用

這種方法與執行緒池的配合更為緊密

優點:無需先轉化為task,再進行執行

需求示例:使用Callable和執行緒池計算1-100的和

程式碼示例:

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

 

public class Demo03 {

    public static void main(String[] args) throws Exception {

//        1. 建立執行緒池

        ExecutorService es = Executors.newFixedThreadPool(1);

//        2.提交任務Future:表示將要執行任務的結果

        Future<Integer> future =  es.submit(new Callable<Integer>() {

            @Override

            public Integer call() throws Exception {

                System.out.println(Thread.currentThread().getName()+"開始計算");

                int sum=0;

                for (int i=0;i<=100;i++){

                    sum+=i;

                }

                return sum;

            }

        });

//        3.獲取任務結果

       System.out.println(future.get());

 

//        4.關閉執行緒池

        es.shutdown();

    }

}

 

 

 

 

Future介面

功能:表示將要完成的任務的結果

案例需求:使用兩個執行緒,併發計算1-50和51-100的和,再進行彙總統計

Future.get()方法需要等待callable的方法執行完畢才可以繼續執行,即 同步

關於同步、非同步:我們現在手頭有兩個執行緒A\B,A在使用過程中會呼叫B執行緒。同步的含義是例如A需要執行三個部分,在第一個部分時呼叫了B,呼叫之後不繼續執行第二個部分而是等待B被呼叫完之後再繼續執行第二第三個部分。

非同步的含義是,A執行第一部分並呼叫了B執行緒,A不繼續等待B執行緒執行完而接著執行第二部分第三部分。

程式碼示例:

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

 

public class Demo4 {

    public static void main(String[] args) throws Exception{

//        1.建立執行緒池

        ExecutorService es = Executors.newFixedThreadPool(2);

//        2.建立任務及物件

        Future<Integer> future =es.submit(new Callable<Integer>() {

            @Override

            public Integer call() throws Exception {

                int sum=0;

                for(int i=0;i<=50;i++){

                    sum+=i;

                }

                return sum;

            }

        });

 

        Future<Integer> future2=es.submit(new Callable<Integer>() {

            @Override

            public Integer call() throws Exception {

                int sum=0;

                for(int i=51;i<=100;i++){

                    sum+=i;

                }

                return sum;

            }

        });

//      3.獲取結果

        int sum=future.get()+future2.get();

        System.out.println("結果是" + sum);

 

//        4.關閉執行緒

        es.shutdown();

    }

}