android开发笔记之异步FutureTask

FutureTask概念

FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提供 start cancel 操作,可以查询计算是否已经完成,并且可以获取计算的结果。结果只可以在计算完成之后获取,get方法会阻塞当计算没有完成的时候,一旦计算已经完成,那么计算就不能再次启动或是取消。

一个FutureTask 可以用来包装一个 Callable 或是一个runnable对象。因为FurtureTask实现了Runnable方法,所以一个 FutureTask可以提交(submit)给一个Excutor执行(excution).

FutureTask使用场景

FutureTask可用于异步获取执行结果或取消执行任务的场景。通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过FutureTask的get方法异步获取执行结果,因此,FutureTask非常适合用于耗时的计算,主线程可以在完成自己的任务后,再去获取结果。另外,FutureTask还可以确保即使调用了多次run方法,它都只会执行一次Runnable或者Callable任务,或者通过cancel取消FutureTask的执行等。

java FutureTask执行多任务计算的例子

利用FutureTask和ExecutorService,可以用多线程的方式提交计算任务,主线程继续执行其他任务,当主线程需要子线程的计算结果时,在异步获取子线程的执行结果。

public class FutureTest1 {

    public static void main(String[] args) {
        Task task = new Task();// 新建异步任务
        FutureTask future = new FutureTask(task) {
            // 异步任务执行完成,回调
            @Override
            protected void done() {
                try {
                    System.out.println("future.done():" + get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        };
        // 创建线程池(使用了预定义的配置)
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(future);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        // 可以取消异步任务
        // future.cancel(true);

        try {
            // 阻塞,等待异步任务执行完毕-获取异步任务的返回值
            System.out.println("future.get():" + future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    // 异步任务
    static class Task implements Callable {
        // 返回异步任务的执行结果
        @Override
        public Integer call() throws Exception {
            int i = 0;
            for (; i < 10; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + "_"
                            + i);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return i;
        }
    }

}

android FutureTask使用样例

packages\apps\SnapdragonGallery\src\com\android\gallery3d\app\AlbumSetDataLoader.java

private static final int MSG_RUN_OBJECT = 3;

private final Handler mMainHandler;
.......................
        mMainHandler = new SynchronizedHandler(activity.getGLRoot()) {
            @Override
            public void handleMessage(Message message) {
                switch (message.what) {
                    case MSG_RUN_OBJECT:
                        ((Runnable) message.obj).run();
                        return;
           }
......................             
    private  T executeAndWait(Callable callable) {
        FutureTask task = new FutureTask(callable);
        mMainHandler.sendMessage(
                mMainHandler.obtainMessage(MSG_RUN_OBJECT, task));
        try {
            return task.get();
        } catch (InterruptedException e) {
            return null;
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }
.................................
    private class UpdateContent implements Callable {
        private final UpdateInfo mUpdateInfo;

        public UpdateContent(UpdateInfo info) {
            mUpdateInfo = info;
        }

        @Override
        public Void call() {
       ..............
        }
    }
....................
executeAndWait(new UpdateContent(info));

自己写的Demo

主要功能是开启一个后台耗时操作,同时与主UI线程通信,更新主UI界面.

public class MainActivity extends AppCompatActivity {

    private final static String TAG = "MainActivity";

    private final static int UPDEAT_UI =1;

    private TextView textView;
    private Button button_FutureTask;

    private Task task = new Task();// 新建异步任务
    private FutureTask futureTask = new FutureTask(task) {
        @Override
        protected void done() {
            try {
                Log.i(TAG,"futureTask---done--get():"+get());
                Message message = new Message();
                message.what = UPDEAT_UI;
                message.arg1 = get();
                handler.sendMessage(message);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    };

    private ExecutorService executor = Executors.newCachedThreadPool();

    class Task implements Callable {
        @Override
        public Integer call() throws Exception {
            int i = 0;
            for (; i < 10; i++) {
                try {
                    Log.i(TAG,Thread.currentThread().getName() + "_" + i);
                    Log.i(TAG,"handler.sendEmptyMessage--UPDEAT_UI");
                    Message message = new Message();
                    message.what = UPDEAT_UI;
                    message.arg1 = i;
                    handler.sendMessage(message);
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return i;
        }
    }


    private  Handler handler =  new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch(msg.what){
                case UPDEAT_UI:
                    textView.setText("UPDEAT_UI--"+ msg.arg1);
                    Log.i(TAG,"handler.handleMessage--UPDEAT_UI--"+msg.arg1);
                    break;
                default :
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        textView = (TextView) findViewById(R.id.textView);

        button_FutureTask = (Button) findViewById(R.id.button_FutureTask);
        button_FutureTask.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.i(TAG,"button_FutureTask---onClick");
                executor.execute(futureTask);
            }
        });
    }
}

参考资料

1.Java进阶之FutureTask的用法及解析
https://blog.csdn.net/chenliguan/article/details/54345993

你可能感兴趣的:(android开发笔记)