Android線程總結一

自己寫了很多博客了吧,今天在寫項目的時候,需要把之前使用的一些AsyncTask的內容切換成線程池,結果發現,我竟然沒有寫過這樣的總結,真的是太大意了,所以我現在就把之前使用過的關於線程的問題,不管是AsyncTask也好,還是線程池也好,或者說是Handler,做一個全面的總結,爲自己以後複習留下個記錄

AsyncTask

關於定義

AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

這個是官網給出的解釋,意思就是說(自己的翻譯,湊合看吧)
AsyncTask能夠適當和簡單的使用UI線程。這個類允許你執行後臺操作和公佈結果到UI線程,而不需要操作線程或者handler

這裏不是關鍵,關鍵的實在下面

AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as {@link Executor}, {@link ThreadPoolExecutor} and {@link FutureTask}.

這句話比較長,具體的意思
AsyncTask是一個幫助類,可以讓我們去執行一些比較小,耗時比較短的線程異步操作,但是如果你的耗時操作比較長,建議你不要使用這樣的方式,還是使用線程池比較好

具體的關於AsyncTask的操作,請查看另外一個博客[android2017年面試]

線程池框架、Executor、ThreadPoolExecutor

Android中的線程池框架,跟Java的是一樣的,所以,我們這裏直接給大家解釋
Android中的線程池框架分爲3個部分
1. 任務:包括被執行任務需要實現的接口類:Runnable 或 Callable
2. 任務的執行器:包括任務執行機制的核心接口類Executor,以及繼承自Executor的EexcutorService接口
3. 執行器的創建者,工廠類Executors

Executor 和 ExecutorService

Executor只是一個接口,它是Java/Android線程池框架的基礎,它將任務的提交與任務的執行分離開來。
ExecutorService繼承自Executor,有兩個關鍵類實現了ExecutorService接口:ThreadPoolExecutor和ScheduledThreadPoolExecutor。
- ThreadPoolExecutor 是線程池的核心實現類,用來執行被提交的任務
- ScheduledThreadPoolExecutor 也是一個實現類,可以在給定的延遲後運行命令,或者定期執行命令。它比Timer更靈活,功能更強大
繼承關係

Executors工廠類

Executors是一個工廠類,它不繼承任何其它類,它通過ThreadPoolExecutor、ScheduledThreadPoolExecutor創建出四種不同的線程池,分別爲
1. newCachedThreadPool 創建一個可緩存線程池,線程池的最大長度無限制,但如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
Executors.java

public static ExecutorService newCachedThreadPool() {  
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  
                                     60L, TimeUnit.SECONDS,  
                                     new SynchronousQueue<Runnable>());  
}  

使用實例

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();  
for (int i = 0; i < 10; i++) {  
    final int index = i;  
    try {  
        Thread.sleep(index * 1000);  
    } catch (InterruptedException e) {  
        e.printStackTrace();  
    }  

    cachedThreadPool.execute(new Runnable() {  

        @Override  
        public void run() {  
            System.out.println(index);  
        }  
    });  
} 
  1. newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待
    Executors.java
public static ExecutorService newFixedThreadPool(int nThreads) {  
    return new ThreadPoolExecutor(nThreads, nThreads,  
                                  0L, TimeUnit.MILLISECONDS,  
                                  new LinkedBlockingQueue<Runnable>());  
} 

使用實例

for (int i = 0; i < 10; i++) {  
    final int index = i;  
    fixedThreadPool.execute(new Runnable() {  

        @Override  
        public void run() {  
            try {  
                System.out.println(index);  
                Thread.sleep(2000);  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
    });  
} 
  1. newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行
    Executors.java
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {  
    return new ScheduledThreadPoolExecutor(corePoolSize);  
} 

實用實例:延時三秒執行

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);  
scheduledThreadPool.schedule(new Runnable() {  

    @Override  
    public void run() {  
        System.out.println("delay 3 seconds");  
    }  
}, 3, TimeUnit.SECONDS); 

延時一秒每三秒執行一次

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {  

    @Override  
    public void run() {  
        System.out.println("delay 1 seconds, and excute every 3 seconds");  
    }  
}, 1, 3, TimeUnit.SECONDS);  
  1. newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
    Executors.java
public static ExecutorService newSingleThreadExecutor() {  
    return new FinalizableDelegatedExecutorService  
        (new ThreadPoolExecutor(1, 1,  
                                0L, TimeUnit.MILLISECONDS,  
                                new LinkedBlockingQueue<Runnable>()));  
}

實用實例

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();  
for (int i = 0; i < 10; i++) {  
    final int index = i;  
    singleThreadExecutor.execute(new Runnable() {  

        @Override  
        public void run() {  
            try {  
                System.out.println(index);  
                Thread.sleep(2000);  
            } catch (InterruptedException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
    });  
}  

寫一個例子:

/**
 * Created: niupule
 * Date: 2018/5/21  下午2:37
 * E-mail:[email protected]
 * des:
 *  線程池管理類
 */

public class ThreadPoolManager {

    //單例模式
    private static ThreadPoolManager manager = new ThreadPoolManager();

    public static ThreadPoolManager getInstance() {
        return manager;
    }

    //核心線程池的數量,能夠同時執行線程的數量
    private int corePoolSize;
    //最大線程池數量
    private int maxPoolSize;
    //存活時間
    private long keepAliveTime = 1;
    //時間計量單位
    private TimeUnit unit = TimeUnit.HOURS;
    //線程池對象
    private ThreadPoolExecutor executor;

    //構造方法
    private ThreadPoolManager() {
        //給corePoolSize賦值:當前設備可用處理器核心數*2 + 1,能夠讓cpu的效率得到最大程度執行(有研究論證的)
        corePoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
        maxPoolSize = corePoolSize;
        executor = new ThreadPoolExecutor(
                corePoolSize,//當某個核心任務執行完畢,會依次從緩衝隊列中取出等待任務
                maxPoolSize,//5,先corePoolSize,然後new LinkedBlockingQueue<Runnable>(),然後maximumPoolSize,但是它的數量是包含了corePoolSize的
                keepAliveTime,//表示的是maximumPoolSize當中等待任務的存活時間
                unit,
                new LinkedBlockingQueue<Runnable>(),//緩衝隊列,用於存放等待任務,Linked的先進先出
                Executors.defaultThreadFactory(),//創建線程的工廠
                new ThreadPoolExecutor.AbortPolicy()//用來對超出maximumPoolSize的任務的處理策略
        );
    }

    //執行任務
    public void execute(Runnable runnable){
        if(runnable == null)
            return;
        executor.execute(runnable);
    }

    //從線程池中移除任務
    public void remove(Runnable runnable){
        if (runnable == null)
            return;
        executor.remove(runnable);
    }
}

這裏還需要添加一個線程

/**
 * Created: niupule
 * Date: 2018/5/21  下午2:50
 * E-mail:[email protected]
 * des:
 * 子線程,瀏覽本地文件
 */

public class FilterFiles implements Runnable {

    //系統文件根目錄
    private File rootAll = new File(CommonUtil.getExternalStorageDirectory());
    //需要查找的文件類型
    private String[] docType = {};
    //需要返回給的數據
    private List<File> files ;
    //handler對象
    private Handler handler;

    //構造方法
    public FilterFiles(String[] docType,Handler handler){
        files = new ArrayList<File>();
        this.docType = docType;
        this.handler = handler;
    }

    @Override
    public void run() {
        //耗時操作執行循環遍歷
        FindAllTypeDocment(rootAll);
        //執行完成之後,返回files數據
        //獲取Message對象
        Message msg = Message.obtain();
        //設置返回的flag
        msg.what = 100;
        msg.obj = files;
        handler.sendMessage(msg);
    }

    //遞歸遍歷數據
    public void FindAllTypeDocment(File root){
        if(root.isDirectory()) {
            File[] fileArray = root.listFiles();
            for (int i = 0; i < fileArray.length; i++) {
                File f = fileArray[i];
                if (f.isDirectory()) {
                    FindAllTypeDocment(f);
                } else if (f.getName().endsWith(docType[0]) || f.getName().endsWith(docType[1])) {
                    files.add(f);
                }
            }
        }
    }

}

在使用的時候,需要創建一個新的handler對象,並且使用的時候新建線程對象

public class LocalDocFragment extends Fragment implements LocalAllFileItemCallback{
    //視圖的recyclerview
    private RecyclerView recyclerView;
    //視圖適配器
    private LocalAllFileAdapter adapter;
    //需要顯示的文件列表集合
    private List<File> files = new ArrayList<File>();
    //無數據顯示樣式
    private LinearLayout local_doc_nodata;
    //sqlite數據庫操作
    private RecentFileDao dao = new RecentFileDao();
    //加載進度
    private LinearLayout local_doc_loading;
    private ProgressBar progressBar;
    //數據加載的handler
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 100:
                    files = (List<File>) msg.obj;
                    if (files != null && files.size() > 0) {
                        recyclerView.setAdapter(adapter = new LocalAllFileAdapter(getContext(), files, LocalDocFragment.this));
                        recyclerView.addItemDecoration(new RecycleViewItemDecoration());
                        local_doc_nodata.setVisibility(View.GONE);
                    } else {
                        local_doc_nodata.setVisibility(View.VISIBLE);
                    }
                    //關閉進度條
                    local_doc_loading.setVisibility(View.GONE);
                    progressBar.setVisibility(View.GONE);
                    break;
                case 101:
                    break;
            }
        }
    };

    public static LocalDocFragment newIstance() {
        LocalDocFragment localDocFragment = new LocalDocFragment();
        return localDocFragment;
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_local_doc, null);
        recyclerView = view.findViewById(R.id.local_doc_recycleview);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        local_doc_nodata = view.findViewById(R.id.local_doc_nodata);
        local_doc_loading = view.findViewById(R.id.local_doc_loading);
        progressBar = view.findViewById(R.id.local_doc_progressbar);
        //讓加載頁面顯示
        local_doc_loading.setVisibility(View.VISIBLE);
        progressBar.setVisibility(View.VISIBLE);
        //從線程池中拿到數據
        ThreadPoolManager.getInstance().execute(new FilterFiles(new String[]{".doc",".docx"},handler));
        return view;
    }

    /**
     * 點擊其中的選項之後需要執行的操作
     */
    @Override
    public void onItemClick(View view, int position) {
        if (files != null && files.size() > position) {
            File file = files.get(position);
            IFile iFile = new LocalFile(file.toURI());
            FileUtils.open(iFile, getActivity());
            File file_recent = files.get(position);
            dao.addRecentFile(file_recent.getName(), file_recent.getAbsolutePath(), FileUtils.generateTime(file_recent), FileUtils.generateSize(file_recent));
            EventBus.getDefault().post(new Msg_Sql());
        }
    }

}
發佈了53 篇原創文章 · 獲贊 8 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章