2022年2月26日 星期六

Android Studio - ExecutorService(線程池)(五十二)

Android Studio - ExecutorService(線程池)(五十二):

當要使用大量的非同步任務,不想每次都創建子線程,可以使用 ExecutorService(線程池),令到減輕每個非同步任務的調用開銷和提高性能。

Android ExecutorService(線程池)
new Thread() 的缺點:
  • 每次 new Thread() 耗費性能
  • 調用 new Thread() 創建的線程缺乏管理,被稱為野線程,而且可以無限制創建,之間相互競爭,會導致過多佔用系統資源導致系統癱瘓
  • 不利於擴展,比如如定時執行、定期執行、線程中斷

ExecutorService 的優點:
  • 重用存在的線程,減少物件創建、消亡的開銷,性能佳
  • 可有效控制最大併發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞,提供定時執行、定期執行、單線程、併發數控制等功能

通過 Executors 的靜態方法來創建,一般有三種:
  • 單線程:Executors.newSingleThreadExecutor()
  • 固定數量線程:Executors.newFixedThreadPool()
  • 動態線程:Executors.newCachedThreadPool()

ThreadPoolExecutor 類的典型構造:

public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue) {

        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

             Executors.defaultThreadFactory(), defaultHandler);

    }


ThreadPoolExecutor 的配置參數:

public ThreadPoolExecutor(int corePoolSize,

                      int maximumPoolSize,

                      long keepAliveTime,

                      TimeUnit unit,

                      BlockingQueue workQueue,

                      ThreadFactory threadFactory,

                      RejectedExecutionHandler handler) {

    this.corePoolSize = corePoolSize;

    this.maximumPoolSize = maximumPoolSize;

    this.workQueue = workQueue;

    this.keepAliveTime = unit.toNanos(keepAliveTime);

    this.threadFactory = threadFactory;

    this.handler = handler;

}


操作系統:Windows 7 64-bit 版本
開發環境:Android Studio 4.0.1 版本
原程式:C:\Development\Development_Android\Android_Project\DIY-Android-009-01D ExecutorService
程式:C:\Development\Development_Android\Android_Project\DIY-Android-009-01D ExecutorService

MainActivity.xml:

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.TextView;

import java.util.concurrent.LinkedBlockingDeque;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

 

public class MainActivity extends AppCompatActivity {

 

    // Gets the number of available cores (not always the same as the maximum number of cores)

    private static int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();

    // Sets the amount of time an idle thread waits before terminating

    private static final int KEEP_ALIVE_TIME = 1000;

    // Sets the Time Unit to Milliseconds

    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.MILLISECONDS;

    // Used to update UI with work progress

    private int count = 0;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

    }

 

    // This is the runnable task that we will run 100 times

    private Runnable runnable = new Runnable() {

        @Override

        public void run() {

            // Do some work that takes 100 milliseconds

            try {

                Thread.sleep(100);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

 

            // Update the UI with progress

            runOnUiThread(new Runnable() {

                @Override

                public void run() {

                    count++;

                    String msg = count < 100 ? "Thread Working " : "Finished ... ";

                    updateStatus(msg + count);

                }

            });

        }

    };

 

    // Button click and performs work using a thread pool

    public void buttonClickThreadPool(View view) {

        count = 0;

        ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(

                NUMBER_OF_CORES + 2,        // Initial pool size

                NUMBER_OF_CORES + 2,   // Max pool size

                KEEP_ALIVE_TIME,       // Time idle thread waits before terminating

                KEEP_ALIVE_TIME_UNIT,  // Sets the Time Unit for KEEP_ALIVE_TIME

                new LinkedBlockingDeque<Runnable>());  // Work Queue

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

            mThreadPoolExecutor.execute(runnable);

        }

    }

 

    private void updateStatus(String msg) {

        ((TextView) findViewById(R.id.text)).setText(msg);

    }

}


active_main.xml:

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:fillViewport="false">

    <LinearLayout

        android:orientation="vertical"

        android:layout_width="match_parent"

        android:layout_height="match_parent">

 

        <TextView

            android:id="@+id/text"

            android:layout_width="match_parent"

            android:layout_height="53dp"

            android:text="TextView" />

 

        <Button

            android:id="@+id/poolButton"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:onClick="buttonClickThreadPool"

            android:text="Thread Pool" />

    </LinearLayout>

</ScrollView>



Android Studio ExecutorService(線程池)程式
2022年 2月 26日(Sat)天氣報告
氣溫:37.0°F / 3.0°C @ 07:00
風速:每小時 5公里
降雨機會:1%
相對濕度:百分之 53%
天氣:晴

沒有留言:

張貼留言