Android线程与线程池

一.特殊的线程

1.AsynTask

底层用到了线程池,封装了线程池和Handler,主要是为了方便开发者在子线程中更新UI

2.IntentService(不完整???)

内部采用HandlerThread来执行任务,当任务执行完毕后IntentService会自动退出,底层直接使用了线程(从任务执行的角度来看,IntentService的作用很像一个后台线程,但是IntentService是一种服务,他不容易被系统杀死从而可以尽量保证任务的执行)

3.HandlerThread

是一种具有消息循环的线程,在它的内部可以使用Handler,底层直接使用了线程

二.Android中的线程形态

1.1 参数及方法介绍

1.AsyncTask是一个抽象的泛型类,它提供了Params,Progress和Result这三个泛型参数,其中Params表示参数的类型Progress表示后台任务的执行进度的类型,而Result则表示后台任务的返回结果的类型

如果AsyncTask确实不需要传递具体的参数,那么这三个泛型参数可以用Void来代替,AsyncTask这个类的声明如下所示。

public abstract class AsyncTask<Params ,Progress ,Result>

(1)onPreExecute

在主线程执行,在异步任务执行之前,此方法会被调用,一般可用于做一些准备工作

(2)doInBackground(Params...params)

在线程池中执行,此方法用于执行异步任务,params参数表示异步任务的的输入参数,在此方法中可以通过publishProgress方法来更新任务的进度,publicProgress方法会调用onProgressUpdate方法。另外此方法需要返回计算结果给onPostExecute

(3)onProgressUpdate(Progress...values)

在主线程中执行,当后台任务的执行进度发生改变时此方法会被调用。

(4)onPostExecute(Result result)

在主线程中执行,异步任务执行之后,此方法会被调用,其中Result参数是后台任务的返回值,即doInBackgroud的返回值

(5)onCancelled

在主线程中执行 异步任务取消时调用,这个时候onPostExecute则不会调用

1.2  AsyncTask在具体的使用过程中也是有一些条件限制

(1)AsyncTask的类必须在主线程中加载,这就意味着第一个访问AsncTask必须发生在主线程,当然这个过程在Android4.1及以上版本中已经被系统已经自动完成。在Android5.0的源码中,可以查看ActivityThread的main方法,他会调用AsyncTask的init方法,这就满足了AsyncTask的类必须在主线程中进行加载这个条件(为什么要满足这个条件,因为要切回主线程的Handler必须是在主线程中创建,然后这个Handler是AsyncTask的内部静态类,所以这个类必须在主线程加载

(2)AsyncTask的对象必须在主线程中创建

(3)Execute方法必须在UI线程调用

(4)一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行异常

(5)在Android1.6之前,AsyncTask是串行执行任务的,Android1.6的时候AsyncTask开始采用线程池里处理并行任务,但是Android3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务,尽管如此,在Android3.0以及后续的版本中,我们仍然可以通过AsynTask的executeOnExecutor方法并行执行任务

1.3源码分析

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
    return executeOnExecutor(sDefaultExecutor, params);
}

sDefaultExecutor串行的线程池

//executeOnExecutor    //1

@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
        Params... params) {
    if (mStatus != Status.PENDING) {
        switch (mStatus) {
            case RUNNING:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task is already running.");
            case FINISHED:
                throw new IllegalStateException("Cannot execute task:"
                        + " the task has already been executed "
                        + "(a task can be executed only once)");
        }
    }

    mStatus = Status.RUNNING;

    onPreExecute();

    mWorker.mParams = params;
    exec.execute(mFuture);

    return this;
}

//2

mFuture = new FutureTask<Result>(mWorker) {
    @Override
    protected void done() {
        try {
            postResultIfNotInvoked(get());
        } catch (InterruptedException e) {
            android.util.Log.w(LOG_TAG, e);
        } catch (ExecutionException e) {
            throw new RuntimeException("An error occurred while executing doInBackground()",
                    e.getCause());
        } catch (CancellationException e) {
            postResultIfNotInvoked(null);
        }
    }
};

可以看到把Params封装成FutureTask(这个事并发类在这充当Runnable)对象

最上面写了public static final Executor SERIAL_EXECUTOR = new SerialExecutor()

默认用的就是这个线程池

//3

private static class SerialExecutor implements Executor {
    final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
    Runnable mActive;

    public synchronized void execute(final Runnable r) {
        mTasks.offer(new Runnable() {
            public void run() {
                try {
                    r.run();
                } finally {
                    scheduleNext();
                }
            }
        });
        if (mActive == null) {
            scheduleNext();
        }
    }

    protected synchronized void scheduleNext() {
        if ((mActive = mTasks.poll()) != null) {
            THREAD_POOL_EXECUTOR.execute(mActive);
        }
    }
}

这时候就是把任务队列mTasks

scheduleNext()一个AsyncTask任务执行完后,调用这个来执行下一个AsyncTask

//4

mWorker = new WorkerRunnable<Params, Result>() {
    public Result call() throws Exception {
        mTaskInvoked.set(true);

        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        //noinspection unchecked
        Result result = doInBackground(mParams);
        Binder.flushPendingCommands();
        return postResult(result);
    }
};

由于FutureTask的run方法会调用mWorker的call方法最终会在线程池中执行,在这个方法中先将mTaskInvoked设为true,表示当前任务已经被调用过了,然后执行AsyncTask的doInBackgroud方法,接着传递给PostResult

AsyncTaks中有两个线程池

1.SerialExecutor

用于任务的队列

2.THREAD_POOL_EXECUTOR(也叫InternalHandler)

用于将执行环境从线程池切换到主线程

//5

private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    message.sendToTarget();
    return result;
}

//6

private static Handler getHandler() {
    synchronized (AsyncTask.class) {
        if (sHandler == null) {
            sHandler = new InternalHandler();
        }
        return sHandler;
    }
}

//7

private static class InternalHandler extends Handler {
    public InternalHandler() {
        super(Looper.getMainLooper());
    }

    @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
    @Override
    public void handleMessage(Message msg) {
        AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
        switch (msg.what) {
            case MESSAGE_POST_RESULT:
                // There is only one result
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
        }
    }
}

可以看出sHandler是一个静态的Handler对象,为了能够将执行环境切换到主线程

这就要求1.sHandler这个对象必须在主线程中创建(在哪创建,handler里面的各种函数才能在哪执行,这里需要在主线程)----------->2.由于静态成员会在加载类的时候进行初始化,因此这就变相要求AsyncTask的类必须在主线程创建(因为sHandler是AsyncTask的静态成员变量),否则同一个进程中的AsyncTask都将无法正常工作

//8

private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

1.4简单实验(证明AsyncTaks即可串行也是并行)

public class MainActivity extends Activity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.bt_start_task).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //串行
        new MyAsyncTask("我是串行task1").execute();
//        new MyAsyncTask("我是串行task2").execute();
//        new MyAsyncTask("我是串行task3").execute();
//        new MyAsyncTask("我是串行task4").execute();
//        new MyAsyncTask("我是串行task5").execute();
//        public final AsyncTask<Params, Progress, Result> execute(Params... params) {
//            return executeOnExecutor(sDefaultExecutor, params);
//        }

        //并行
        new MyAsyncTask("我是并行task1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
        new MyAsyncTask("我是并行task2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
        new MyAsyncTask("我是并行task3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
        new MyAsyncTask("我是并行task4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
        new MyAsyncTask("我是并行task5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");

    }

    private static class MyAsyncTask extends AsyncTask<String ,Integer,String>{

        private String mName = "AsyncTask";

        public MyAsyncTask(String mName) {
            super();
            this.mName = mName;
        }

        @Override
        protected String doInBackground(String... params) {
            SystemClock.sleep(3000);
            return mName;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("xcqw   "+mName+"  execute finish at"+df.format(new Date()));
        }
    }

}

可以通过看打印得出既可以串行也可以并行,但是为什么呢?

串行调用execute和并行调用executeOnExecutor 最后都是调用 executeOnExecutor,只是传的参数不一样

//串行传的参数(默认参数)

private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

从队列中依次取出任务然后调用THREAD_POOL_EXECUTOR.execute(mActive);

//并行传的参数THREAD_POOL_EXECUTOR

每次都直接调用这个THREAD_POOL_EXECUTOR.execute,所以当然并行了

1.5简单实践

//版本更新功能用AsyncTask实现

//updateProgressDialogTask.java

package com.weixin.updateprogressdialog.task;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;

import com.weixin.updateprogressdialog.dialog.UpdateProcessDialog;
import com.weixin.updateprogressdialog.utils.ToastUtils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by xiongchao on 2015/10/29.
 */
public class UpdateTask extends AsyncTask<Object, Integer, File> {
    //下载的路径
    private String urlpath;
    private UpdateProcessDialog mydialog;
    private Handler threadhandler;
    private Activity activity;
    private FileOutputStream fos;
    private BufferedInputStream bis;
    private InputStream is;
    //下载成功后重命名的文件
    private  String  updateSuccessFilePath;
    //下载过程中存放apk的地址
    private String  updatingStorePath;
    //当前运行的线程
    private UpdateTask mCurrentTaks;
    public  static boolean isStopDownload = false;

//    public boolean isStopDownload() {
//        return isStopDownload;
//    }
//
//    public void setIsStopDownload(boolean isStopDownload) {
//        this.isStopDownload = isStopDownload;
//    }

    public void setUpdateComponents(UpdateTask Task,String serverversion,String updatingStorePath) {
        this.mCurrentTaks = Task;
        this.updateSuccessFilePath = Environment.getExternalStorageDirectory()+"/MyWeiXinUpDate/"+"update1"+serverversion+".apk";
        this.updatingStorePath = updatingStorePath;
    }

    public UpdateTask(Activity activity,String urlpath, UpdateProcessDialog dialog,Handler threadhandler) {

        this.activity = activity;
        this.urlpath = urlpath;
        this.mydialog = dialog;
        this.threadhandler = threadhandler;
    }

    // 主线程运行, 预加载
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    // 子线程运行, 异步加载逻辑在此方法中处理
    @Override
    protected File doInBackground(Object... params) {
        System.out.println("xcq  " + "任务开始");
        urlpath = (String) params[0];
        //如果相等的话表示当前的sdcard挂载在手机上并且是可用的
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            try {
                URL url = new URL(urlpath);
                System.out.println("xcq  " + "去请求连接");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //设置连接超时
                conn.setConnectTimeout(5000);
                //设置下载超时
                conn.setReadTimeout(60000);
                //是否连接成功//如果没有网络会在这里直接跳到异常
                System.out.println("xcq  " + "去请求响应码");
                //响应码这阻塞时间较长,所以先打开dialog
                threadhandler.post(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("xcq  mydialog   3"+mydialog);
                        if(mydialog != null) {
                            mydialog.show();
                        }
                    }
                });
                int code = conn.getResponseCode();
                if( 200 == code)
                {
                    File file = new File(updatingStorePath);
                    File suceessFile = new File(updateSuccessFilePath);
                    //如果已经下载过直接去安装
                    if (suceessFile.exists()) {
                        return suceessFile;
                    }
                    //获取到文件的大小
                    long length = conn.getContentLength();
                    is = conn.getInputStream();
                    fos = new FileOutputStream(file);
                    bis = new BufferedInputStream(is);
                    byte[] buffer = new byte[1024];
                    int len;
                    int total = 0;
                    boolean renameflag = false;
                    while ((len = bis.read(buffer)) != -1) {
                        fos.write(buffer, 0, len);
                        total += len;
                        if (isStopDownload) {
                            stopDownLoad();
                            break;
                        }
                        int percent = (int) (total * 100 / length);

                        if(percent == 100){
                            System.out.println("xcq  " + "下载成功");
                            //如果下载成功,下载文件重命名
                            renameflag = file.renameTo(suceessFile);
                            if(renameflag == false){
                                throw new Exception("文件重命名失败");
                            }
                        }
                        //获取当前下载量//进入progressupdate更新
                        publishProgress(percent);

                    }
                    fos.close();
                    bis.close();
                    is.close();
                    myDialogDismiss(mydialog);
                    if(mCurrentTaks != null && renameflag){
                        System.out.println("xcq  " +"is"+isStopDownload);
                        return suceessFile;
                    }else{
                        //如果到这就是中断更新了//还有可能是下载成功后文件重命名失败
                        System.out.println("xcq  " +"is"+isStopDownload);
                        return null;
                    }
                }
                else{
                    //连接服务器失败//服务器返回参数不是200(OK)
                    ToastUtils.show(activity, "连接服务器异常,请检查网络");
                }

            } catch (Exception e) {
                System.out.println("xcq  异常" + e.toString());
                try {if (fos != null){fos.close();}} catch (IOException e1) {e1.printStackTrace();}
                try {if (bis != null) fos.close();} catch (IOException e1) {e1.printStackTrace();}
                try {if (fos != null) is.close();} catch (IOException e1) {e1.printStackTrace();}
                ToastUtils.show(activity,"下载失败,请检查网络");
                stopDownLoad();
                e.printStackTrace();
            }
        } else {
            ToastUtils.show(activity,"请检查sd卡是否安装正确");
            stopDownLoad();
            return null;
        }

        return null;
    }

    // 主线程运行, 更新进度
    @Override
    protected void onProgressUpdate(Integer... values) {
        int i = (int) values[0];
        System.out.println("xcq  Update进度" + i+"isStopDownload"+isStopDownload);
        if (mydialog != null) {
            mydialog.show();
            mydialog.updateProgressAndTitle(i);
        }
        super.onProgressUpdate(values);
    }

    // 主线程运行, 更新主界面
    @Override
    protected void onPostExecute(File result) {
        if (mCurrentTaks != null) {
            if (result != null && !mCurrentTaks.isCancelled()) {
                stopDownLoad();
                Intent intent = new Intent();
                //执行动作
                intent.setAction(Intent.ACTION_VIEW);
                //执行的数据类型
                intent.setDataAndType(Uri.fromFile(result), "application/vnd.android.package-archive");
                activity.startActivity(intent);
                System.out.println("xcq  onPostExecute");

            }
        }
        stopDownLoad();
    }

    private void myDialogDismiss(AlertDialog dialog) {
        if (dialog != null) {
            dialog.dismiss();
            dialog = null;
            System.out.println("xcq   dialog置null");
        }
    }

    private void myTaskCancel() {
        if (mCurrentTaks != null) {
            mCurrentTaks.cancel(true);
            mCurrentTaks = null;
        }
    }
    private void stopDownLoad() {
        myTaskCancel();
        myDialogDismiss(mydialog);
        isStopDownload = false;
    }
}

//FirstActivity.java

public class FirstActivity extends Activity {
    private UpdateProcessDialog mydialog;
    private String serverVersion;
    private UpdateTask task;
    private String result = "自行添加下载地址";
    private String updatestorepath = Environment.getExternalStorageDirectory()+"/MyWeiXinUpDate/update.apk";
    private Handler threadhandler= null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        if(threadhandler == null){
            threadhandler = new Handler();
        }

    }

    public void update(View view) {
        if (!UpdateTask.isStopDownload) {
            isVersionsUpdate("1.1");
        } else {
            Toast.makeText(FirstActivity.this, "小点即可,切勿狂按", Toast.LENGTH_SHORT).show();
        }
    }

    private void isVersionsUpdate(final String versions) {

        try {
            final JSONObject json = new JSONObject(result);
            JSONObject requstResult = json.getJSONObject("RequstResult");
            serverVersion = json.get("Versions").toString();
            final String apkurl = json.getString("Download");
            //这个state是从维信理财直接抄过来的
            int state = requstResult.getInt("State");
            if (state == 0) {
                if (versions.compareTo(json.get("Versions").toString()) >= 0) {
                    Toast.makeText(FirstActivity.this, "已是最新版本", Toast.LENGTH_SHORT).show();
                } else {
                    AlertDialog.Builder builder = new AlertDialog.Builder(FirstActivity.this);
                    builder.setTitle("有新版本" + json.get("Versions")
                            + ",是否現在更新?");
                    builder.setPositiveButton("真的确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //开启asynctask下载
                            getApkFromServer(apkurl);
                            //download(apkurl);
                        }
                    });
                    builder.setNegativeButton("取消", null);
                    builder.create().show();
                }
            }
        } catch (Exception e) {
            System.out.println("xcq  异常11" + e.toString());
            e.printStackTrace();
        }
    }

    //   方法一
    public void getApkFromServer(String url) {
        mydialog = UpdateProcessDialog.showDeleteDialog(FirstActivity.this, 100, new UpdateProcessDialog.OnDeleteCancelListener() {

            @Override
            public void onCancel() {
                UpdateTask.isStopDownload = true;
            }
        }, false);
        //dialog一创建就show(为了初始化),所以这里就关闭显示
        mydialog.dismiss();
        task = new UpdateTask(FirstActivity.this,url, mydialog,threadhandler);
        task.setUpdateComponents(task,serverVersion,updatestorepath);
        task.execute(url);

    }

2.HandlerThread

Thread(普通) run方法执行了一个耗时任务

HandlerThread内部创建了消息队列,外部需要通过Hanlder类的消息方式来通知他执行一个具体任务,由于HandlerThread的run方法是一个无限循环,因此当明确不需要再使用HandlerThread时,用quit或者quitSafely方法来终止线程的执行。

3.IntentService

三: Android线程池

线程池的优点

(1)重用线程池的线程,避免线程的创建和销毁所带来的性能开销

(2)可以控制线程池的最大并发数,避免大量的线程之间相互抢占系统资源而导致阻塞

(3)能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行

Android线程池的概念源于Java中的Executor,Executor是一个接口,Android中真正的线程池的实现为ThreadPoolExecutor,Android中的线程池都是直接或间接通过配置ThreadPoolExecutor来实现的.

1.5.1ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory) {

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

threadFactory, defaultHandler);

}

corePoolSize :核心线程数,默认情况下,即使他们处于闲置状态(IDLE),核心线程也会在线程池中一直存活.

除非将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为True,那么闲置的核心线程在等待新任务到来时会有超时策略,这个时间间隔由KeepAliveTime所指定,超过这个时间核心线程就会被停止

maximumPoolSize:线程池所能容纳的最大线程数,当活动线程数达到这个数值后,后续的新任务将会被阻塞。

keepAliveTime

非核心线程:超过这个时长,非核心线程就会被回收

核心线程(当ThreadPoolExecutor的allowThreadTimeOut属性设置为True才会受影响):影响上面有说

Unit:用于指定KeepAliveTime参数的时间单位

workQueue

线程池中的任务队列,通过线程池的execute方法提交的Runnable对象会存储在这个参数

threadFactory

线程工厂,为线程池提供创建新线程的功能。ThreadFactory是一个接口,他只有一个方法:Thread newThread(Runnable r)

defaultHandler

当线程池无法执行新任务时,这可能是由于任务队列已满或者无法成功执行任务,有几个策略,默认是abortPolicy,用了这个就会直接抛异常

1.5.2ThreadpoolExecutor执行任务时大致遵循如下规则:

(1).如果线程池的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务

(2)如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入任务队列中等待执行

(3)如果步骤2插入失败,这往往是任务队列满了,这个时候如果线程数量位达到线程池规定的最大值,那么会立即启动一个非核心线程来执行任务

(4)如果步骤3的线程数量已经达到线程池规定的最大值,那么拒绝执行此任务,就会调用defaultHandler

哪些参数的配置在AsyncTask中可以清晰的看出来

时间: 2024-10-07 23:53:02

Android线程与线程池的相关文章

Android的线程和线程池

原文链接,转载请注明出处 http://sparkyuan.me/2016/03/25/Android的线程和线程池/ 在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作.线程的创建和销毁的开销较大,所以如果一个进程要频繁地创建和销毁线程的话,都会采用线程池的方式. Android中线程的形态 传统的Thread AsyncTask HandlerThread IntentS

Android开发之线程池使用总结

线程池算是Android开发中非常常用的一个东西了,只要涉及到线程的地方,大多数情况下都会涉及到线程池.Android开发中线程池的使用和Java中线程池的使用基本一致.那么今天我想来总结一下Android开发中线程池的使用. OK,假如说我想做一个新闻应用,ListView上有一个item,每个item上都有一张图片需要从网络上加载,如果不使用线程池,你可能通过下面的方式来开启一个新线程: new Thread(new Runnable() { @Override public void ru

Android(线程二) 线程池详解

我们在ListView中需要下载资源时,赞不考虑缓存机制,那么每一个Item可能都需要开启一个线程去下载资源(如果没有线程池),如果Item很多,那么我们可能就会无限制的一直创建新的线程去执行下载任务,最终结果可能导致,应用卡顿.手机反应迟钝!最坏的结果是,用户直接卸载掉该App.所以,我们在实际开发中需要考虑多线程,多线程就离不开线程池.如果你对线程还不了解,可以看看这篇文章,Android(线程一) 线程. 使用线程池的优点: (1).重用线程,避免线程的创建和销毁带来的性能开销: (2).

android线程与线程池-----线程池(二)《android开发艺术与探索》

android 中的线程池 线程池的优点: 1 重用线程池中的线程,避免了线程的创建和销毁带来的性能开销 2 能有效的控制最大并发数,避免大量线程之间因为喜欢抢资源而导致阻塞 3 能够对线程进行简单的管理,提供定时执行以及指定间隔时间循环执行等 android 中的线程池源自java 中的Executor,Executor是一个接口,正真的实现是ThreadPoolExecutor. ThreadPoolExecutor 提供参数配置线程池. 下面是一个常用的构造方法: public Threa

android线程及线程池

众所周知,在UI系统中进行一些耗时操作,都会导致卡顿现象,因为一次刷新在16ms,如果当次操作过了这个时间,那么用户就能感觉到明显的卡顿,甚至引起ANR . 对于这种情况,一般都是再起一个线程,进行一些耗时的操作,通过继承Thread 或者实现Runnable接口,重写run方法,来实现创建新线程,进行耗时操作的需求.由于java的单继承关系,首推实现Runnable方法,这样不会太过臃肿. private void runThread() { Thread t1 = new Thread(ne

《Android开发艺术探索》第11章 Android的线程和线程池

第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界面相关的事情,而子线程则往往用于执行耗时操作.线程的创建和销毁的开销较大,所以如果一个进程要频繁地创建和销毁线程的话,都会采用线程池的方式.(2)在Android中除了Thread,还有HandlerThread.AsyncTask以及IntentService等也都扮演着线程的角色,只是它们具有不

Android中的线程池

总会有线程,总会有队列,等着被执行吧.so,让我们再深深看看线程池: 简介: 线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的.在jdk1.5之后这一情况有了很大的改观.Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用.为我们在开发中处理线程的问题提供了非常大的帮助. 作用: 线程池作用就是限制系统中执行线程的数量.     根据系统的环境情况,可以自动或手动设置线程数量,

【转载】Android中UI线程与后台线程交互设计的5种方法

原帖地址:http://www.cr173.com/html/19165_1.html 在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须要重新开启一个后台线程运行这些任务.然而,往往这些任务最终又会直接或者间接的需要访问和控制UI控件.例如访问网络获取数据,然后需要将这些数据处理显示出来.就出现了上面所说的情况.原本这是在正常不过的现象了,但是android规定除了UI线程外,其他线程都不可以对那些UI控件访问

java中的进程,线程,线程池总结

1.线程与进程 进程 狭义上讲:正在执行的程序,由线程组成,可包含多个线程在运行. 广义上讲:进程是一个具有一定独立功能的程序有关于某个数据集合的一次运行的活动.它可以申请或者拥有系统资源,是一个动态的概念. 进程的概念主要两点:1.进程是一个实体,每一个进程都有自己的地址空间,一般情况下包括文本区域,数据区和堆栈. 线程 为进程中执行的程序片段. 一个线程由线程ID,当前指令针,寄存器和堆栈组成,另外线程是进程的实体,是被系统独立调试的分派的基本单元. 线程是程序中一个单一的顺序控制流程.进程