Android Thread线程

       相信大家对线程肯定不陌生,我们在编程的过程中经常要用到线程,Android提供了多线程支持,在Android程序中,VM采用抢占式调度模式对线程进行调度(基于线程优先级来决定CPU的使用权),android一个重要的机制就是线程+消息。

一,线程进程

       既然说到线程,得先说说进程。一般来说一个android程序对于一个进程(组件元素activity、service、receiver、provider。都有一个process属性可以指定组件运行在哪个进程中,你可以在清单文件中manifest设置组件的进程)所有的组件都在特定进程的主线程中实例化。
       线程:线程是属于进程的。同一个进程下的可以有多个线程。这些线程是共同享该进程占有的资源和地址空间的。线程是进程的一部分,一个没有线程的进程可以看做是单线程的。对于android应用来说,当一个应用启动的时候,系统会默认为它创建一个线程,称为“主线程”(UI线程)。这个线程很重要因为它负责处理调度事件到相关的 user interface widgets,包括绘制事件。你的应用也是在这个线程里面与来自Android UI toolkit (包括来自 android.widget 和 android.view 包的组件)的组件进行交互。因此,这个主线程有时候也被称为 UI 线程。
进程线程总结:
1. 进程让操作系统的并发性成为可能,而线程让进程的内部并发成为可能。
2. 进程是操作系统进行资源分配的基本单位。
3. 线程是操作系统进行调度的基本单。
4. 线程的划分尺度小于进程,线程隶属于某个进程。
5. 进程是程序的一种动态形式,是CPU、内存等资源占用的基本单位,而线程是不能独立的占有这些资源的。
6. 进程之间相互独立,通信比较困难,而线程之间共享一块内存区域,通信比较方便。
7. 进程在执行过程中,包含比较固定的入口、执行顺序和出口,而线程的这些过程会被应用程序所控制。

二,线程的实现(两种方式)

       两种方法,继承Thread类和实现Runnable接口

  • 继承Thread类
           extends Thread 重写run方法做我们想做的事情,start启动线程。 简单代码如下:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new CustomerThread("CustomerThread").start();
    }

    public class CustomerThread extends Thread {

        public CustomerThread(String threadName) {
            super(threadName);
        }

        @Override
        public void run() {
            /** do our things */
        }
    }
  • 实现Runnable接口:run方法里面做我们要做的事情。简单代码如下
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SyncRunnable syncRunnable = new SyncRunnable();
        Thread thread = new Thread(syncRunnable, "syncRunnable");
        thread.start();
    }

    public class SyncRunnable implements Runnable {
        @Override
        public void run() {
            synchronized (this) {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "   synchronizedloop " + i);
                }
            }
        }
    }

注:这两种方法的实现中我都有带上线程的名字。顺便说一点,我们用线程的时候最好给线程加上一个名字,这样我们在看log信息的时候能方便的知道是哪个线程打(默认会thread-0, thread-1什么的)。

三,线程退出

       我们在使用线程的时候经常会碰到这种情况,我们的线程是要一直while执行的(如果不是要一直while执行的thread执行完了就会自动销毁)。这个时候当程序退出的时候我们想要这个while线程也去释放资源。主要有三种方式。

  • 使用退出标志,使线程正常退出
    这个最简单了设置标志位。简单代码如下:
    private boolean exit = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SyncThread syncRunnable = new SyncThread("syncThread");
        syncRunnable.start();
    }

    @Override
    protected void onDestroy() {
        exit = true;
        super.onDestroy();
    }

    public class SyncThread extends Thread {

        public SyncThread(String threadName) {
            super(threadName);
        }

        @Override
        public void run() {
            while(!exit) {
                /** do our things */
            }
        }
    }

在onDestroy方法里面退出。exit = true;

  • 使用interrupt()方法中断线程 (当调用线程的interrupt()方法时,系统会抛出一个InterruptedException异常)
    1)先捕获InterruptedException异常之后通过break来跳出循环,简单代码如下。
    SyncThread syncRunnable = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        syncRunnable = new SyncThread("syncThread");
        syncRunnable.start();
    }

    @Override
    protected void onDestroy() {
        if (null != syncRunnable) {
            syncRunnable.interrupt();
        }
        super.onDestroy();
    }

    public class SyncThread extends Thread {

        public SyncThread(String threadName) {
            super(threadName);
        }
        @Override
        public void run() {
            while(true) {
                /** do our things */
                try {
                    Thread.sleep(5*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    /** exit the while */
                    break;
                }
            }
        }
    }

       2)使用isInterrupted()判断线程的中断标志来退出循环。简单代码如下

    SyncThread syncRunnable = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        syncRunnable = new SyncThread("syncThread");
        syncRunnable.start();
    }

    @Override
    protected void onDestroy() {
        if (null != syncRunnable) {
            syncRunnable.interrupt();
        }
        super.onDestroy();
    }

    public class SyncThread extends Thread {

        public SyncThread(String threadName) {
            super(threadName);
        }
        @Override
        public void run() {
            while(!isInterrupted()) {
                /** do our things */
            }
        }
    }

       3)两者结合使用(推荐) 在线程未进入阻塞的代码段时通过isInterrupted()判断中断来退出循环,在进入阻塞状态后通过通过捕获中断异常来退出循环,简单代码如下

    SyncThread syncRunnable = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        syncRunnable = new SyncThread("syncThread");
        syncRunnable.start();
    }

    @Override
    protected void onDestroy() {
        if (null != syncRunnable) {
            syncRunnable.interrupt();
        }
        super.onDestroy();
    }

    public class SyncThread extends Thread {

        public SyncThread(String threadName) {
            super(threadName);
        }
        @Override
        public void run() {
            while(!isInterrupted()) {
                /** do our things */
                try{
                    Thread.sleep(5*1000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                    break;
                }
            }
        }
    }
  • 使用stop方法强行终止线程(不推荐使用,可能发生不可预料的结果)
    thread.stop() 不安全主要是:thread.stop()调用之后,创建子线程的线程就会抛出ThreadDeatherror的错误,并且会释放子线程所持有的所有锁。一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁的突然释放(不可控制),那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。
四,多线程通信
  • 管道(pipe)属于linux范畴:一条“管道”为两个线程建立一个单向的通道。生产者负责写数据,消费者负责读取数据。简单代码如下
    private PipedReader mRead;
    private PipedWriter mWrite;
    private Thread mThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        try {
            mWrite.write("pipe");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mThread.interrupt();
        try {
            mRead.close();
            mWrite.close();
        } catch (IOException e) {
        }
    }

    private void initData() {
        mRead = new PipedReader();
        mWrite = new PipedWriter();
        try {
            mWrite.connect(mRead);
        } catch (IOException e) {
            e.printStackTrace();
        }

        mThread = new Thread(new ThreadPipe(mRead), "ThreadPipe");
        mThread.start();
    }

    private static class ThreadPipe implements Runnable {
        private final PipedReader reader;
        public ThreadPipe(PipedReader reader){
            this.reader = reader;
        }
        @Override
        public void run() {
            while(!Thread.currentThread().isInterrupted()){
                try {
                    int i;
                    while((i = reader.read()) != -1){
                        char c = (char) i;
                        Log.d("vae_tag", "char = " + c);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

先把PipedReader,PipedWriter关联起来。如mWrite.connect(mRead);然后这里是在UI线程里面写,ThreadPipe 线程里面读log出来。

  • 共享内存:一个变量可以同时被多个线程所访问。这里要特别注意同步和原子操作的问题,这也共享内存容易出错的原因所在,容易出现死锁等。
  • socket:这个应该简单。
  • 消息队列(Hander和Message):这个也是android常用的线程间通信方式,网上也有好多关于这个的博文。主要要理清Thread, Handler,Message,Looper,MessageQueue 之间的关系。
    • Looper:(相当于隧道) 一个线程可以产生一个Looper 对象,Looper负责的就是创建管理一个MessageQueue。
    • MessageQueue(消息队列):里面放的就是Message对象,每一个线程最多只可以拥有一个MessageQueue,通常使用一个Looper对象对该线程的MessageQueue进行管理,每一个MessageQueue都不能脱离Looper而存在。主线程创建时会默认创建MessageQueue,其他的线程不会默认创建。
    • Message(消息):被放入在MessageQueue中。
    • Handler(消息的处理者):Handler负责将需要传递的信息封装成Message,通过调用Handler对象的obtainMessage()来实现,将消息传递给Looper,这是通过Handler对象的sendMessage()来实现的。继而由Looper将Message放入MessageQueue中。当Looper对象看到MessageQueue中含有Message,就将其广播出去。该Handler对象收到该消息后,调用相应的Handler对象的handleMessage()方法对其进行处理。简单来说就是当要发送Message消息的时候Handler告诉对应Thread的Looper有消息到来,Looper把Message放入到MessageQueue当中去。当MessageQueue中有Message的时候该Thread的Looper告诉对应的Thread的Handler来处理消息。
      几个简单例子代码。
      1)UI线程给自己发送消息。
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        handler = new HandlerTest(getMainLooper());
        Message msg = handler.obtainMessage(1, 1, 1, "UI thread send message");
        handler.sendMessage(msg);
    }

    class HandlerTest extends Handler {

        public HandlerTest(Looper looper) {
            super(looper);
        }

        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.d("vae_tag", (String)msg.obj);
        }
    }

       2)UI线程给其他线程发送消息。

    private Button  mButton;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton = (Button) findViewById(R.id.send_message_id);
        new ChildThread("ChildThread").start();
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handler.obtainMessage(1, "UI thread send to child thread").sendToTarget();
            }
        });
    }

    class ChildThread extends Thread {

        public ChildThread(String threadName) {
            super(threadName);
        }

        public void run() {
            Looper.prepare();/** init Looper */
            handler = new ThreadHandler(Looper.myLooper());
            Looper.loop(); /** start Looper */
        }

        class ThreadHandler extends Handler {

            public ThreadHandler(Looper looper) {
                super(looper);
            }

            public void handleMessage(Message msg) {
                Log.d("vae_tag", "child thread receive the message :" + msg.obj);
            }
        }
    }

       3)其他线程给UI线程发送消息。

    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new ChildThread("ChildThread").start();
    }

    class HandlerTest extends Handler {

        public HandlerTest(Looper looper) {
            super(looper);
        }

        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.d("vae_tag", (String) msg.obj);
        }
    }

    class ChildThread extends Thread {

        public ChildThread(String threadName) {
            super(threadName);
        }
        public void run() {
            handler = new HandlerTest(Looper.getMainLooper());
            Message msg = handler.obtainMessage(1, 1, 1, "child thread send the message");

            handler.sendMessage(msg);
        }
    }

       4)其他线程给其他线程发

    private Handler handler;
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton = (Button) findViewById(R.id.send_message_id);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new ChildThread2("ChildThread2").start();
            }
        });
        new ChildThread1("ChildThread1").start();

    }

    class ChildThread1 extends Thread {

        public ChildThread1(String threadName) {
            super(threadName);
        }

        public void run() {
            Looper.prepare();/** init Looper */
            handler = new ThreadHandler(Looper.myLooper());
            Looper.loop(); /** start Looper */
        }

        class ThreadHandler extends Handler {

            public ThreadHandler(Looper looper) {
                super(looper);
            }

            public void handleMessage(Message msg) {
                Log.d("vae_tag", "receive message: " + msg.obj);
            }
        }
    }

    class ChildThread2 extends Thread {

        public ChildThread2(String threadName) {
            super(threadName);
        }

        public void run() {
            Message msg = handler.obtainMessage(1, 1, 1, "child thread send the message");
            handler.sendMessage(msg);
        }
    }

代码都是非常简单的代码,主要抓住Handler往哪个线程发就绑定到对应线程的Looper。
注:关于Message对象,虽然我们可以自己创建一个新的Message,但是更加推荐的是调用handler的obtainMessage方法来获取一个Message对象。这个方法的作用是从系统的消息池中取出一个Message,这样就可以避免Message创建和销毁带来的资源浪费了

五,子线程更新UI的几种方式
  • handler:上面讲过。
  • Activity.runOnUIThread(Runnable):简单代码实现。
    private Button   mButton;
    private TextView mTextView;
    private Activity mActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mActivity = this;
        mTextView = (TextView) findViewById(R.id.text_view_id);
        mButton = (Button) findViewById(R.id.send_message_id);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(){
                    public void run() {
                        mActivity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                mTextView.setText("click ite");
                            }
                        });
                    };
                }.start();
            }
        });
    }
  • View.Post(Runnable)或者View.PostDelayed(Runnabe,long)或者handler.post(new Runnable())三个是一个意思实际上是一样的View.Post(Runnable)源码里面会先获取到当前线程的handler,然后再调用post方法(ViewRootImpl.getRunQueue().post(action);):简单代码如下:
    private Button   mButton;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.text_view_id);
        mButton = (Button) findViewById(R.id.send_message_id);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new ChileThread(mButton).start();
            }
        });
    }

    public class ChileThread extends Thread {
        private Button mButton;
        public ChileThread(Button textView) {
            mButton = textView;
        }

        @Override
        public void run() {
            mButton.post(new Runnable() {
                @Override
                public void run() {
                    mTextView.setText("click ite");
                }
            });
        }
    }

在这里不管是mButton.post() 还是mTextView.post()都是可以的只要是继承View的对象就行。
- AsyncTask:异步任务,主要是四个重要的方法。

  • onPreExecute:运行在UI线程,主要目的是为后台线程的运行做准备。当他运行完成后,他会调用doInBackground方法。
  • doInBackground:运行在后台线程,他用来负责运行任务。他拥有参数Params,并且返回Result。在后台线程的运行当中,为了能够更新作业完成的进度,需要在doInbackground方法中调用PublishProgress方法。该方法拥有参数Progress。通过该方法可以更新Progress的数据。然后当调用完PublishProgress方法,他会调用onProgressUpdate方法用于更新进度。
  • onProgressUpdate:运行在UI线程,主要目的是用来更新UI线程中显示进度的UI控件。他拥有Progress参数。在doInBackground中调用PublishProgress之后,就会自动调onProgressUpdate方法。
  • onPostExecute:运行在UI线程,当doInBackground方法运行完后,他会调用onPostExecute方法,并传入Result。在onPostExecute方法中,就可以将Result更新到UI控件上。
六,HandlerThread

       我们都知道Android中Handler的使用,一般都在UI主线程中执行,因此在Handler接收消息后,处理消息时,不能做一些很耗时的操作,否则将出现ANR错误。Android中专门提供了HandlerThread类,来解决该类问题。HandlerThread类是一个线程专门处理Hanlder的消息HandlerThread用于方便的创建一个含有Looper的线程类。Looper用来创建Handler类,实际上就一个Thread,只不过它比普通的Thread多了一个Looper。一般HandlerThread和Handler类配合使用, Handler将消息发往HandlerThread的消息队列, Handler处理消息。这里启动的是一个新线程 虽然不能直接操作UI 但可以通过Message发送消息来进行操作,其实就是把Handler里面要做的比较耗时的操作放到HandlerThread里面去做,如果有必要的话HandlerThread处理完之后可以再发回给UI线程。
使用HandlerThread的好处:
1. 开发中如果多次使用类似new Thread(){…}.start()这种方式开启一个子线程,会创建多个匿名线程,使得程序运行起来越来越慢,而HandlerThread自带Looper使他可以通过消息来多次重复使用当前线程,节省开支。
2. android系统提供的Handler类内部的Looper默认绑定的是UI线程的消息队列,对于非UI线程又想使用消息机制,那么HandlerThread内部的Looper是最合适的,它不会干扰或阻塞UI线程。
简单的实例代码如下:

public class MainActivity extends ActionBarActivity {

    private Handler         mHandler;
    private MyHandlerThread mHandlerThread;
    private Button          mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandlerThread = new MyHandlerThread("MyHandlerThread");
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerThread);
        mButton = (Button) findViewById(R.id.send_message_id);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHandler.sendEmptyMessage(1);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandlerThread.quit();
    }

    public class MyHandlerThread extends HandlerThread implements Handler.Callback {

        public MyHandlerThread(String name) {
            super(name);
        }

        @Override
        public boolean handleMessage(Message msg) {
            Log.d("vae_tag", "get message");
            return true;
        }
    }
}
七,线程池

       对应数据库连接我们有数据库连接池,对于线程我们也有线程池。线程池是预先创建线程的一种技术。线程池在任务还没到来之前先创建一定数量的线程,放入空闲队列中。这些线程都是处于睡眠状态,即均为启动,不消耗CPU,而只是占用较小的内存空间。当请求到来之后,缓冲池给这次请求分配一个空闲线程,把请求传入此线程中运行,进行处理。当预先创建的线程都处于运行状态,即预制线程不够,线程池可以自由创建一定数量的新线程,用于处理更多的请求。当系统比较闲的时候,也可以通过移除一部分一直处于停用状态的线程。从而达到减少了创建和销毁线程的次数,最大程度的复用对象。

包括三种单一线程池,固定线程池,缓存的线程池使用其他也非常的简单。
下面是固定线程池的简单实例,很简单的例子。

    private Button          mButton;
    private ExecutorService mExecutorService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /** create three threads in the pool */
        mExecutorService = Executors.newFixedThreadPool(3);
        mExecutorService.submit(new ChileThread("ChileThread"));
        mButton = (Button) findViewById(R.id.send_message_id);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mExecutorService.submit(new ChileThread("ChileThread"));
            }
        });
    }

    public class ChileThread extends Thread {
        public ChileThread(String threadName) {
            super(threadName);
        }
        @Override
        public void run() {
            Log.d("vae_tag", "aaaaaaaaaaaaaaaaa");
        }
    }

缓存的线程池 线程池的大小会根据执行的任务数动态分配

mExecutorService = Executors.newCachedThreadPool();

单一线程池

mExecutorService = Executors.newSingleThreadExecutor();
八,Callable,Future

Callable 源码

public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务。Callable是一个泛型接口。call()函数返回的类型就是传递进来的V类型,Callable要配合ExecutorService来使用,采用ExecutorService的submit方法提交。
Callable 和 Runnable方法的区别:
1)Callable定义的方法是call,而Runnable定义的方法是run。
2)Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。
3)Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。

Future表示异步计算的结果,它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。Future的cancel方法可以取消任务的执行,它有一布尔参数,参数为 true 表示立即中断任务的执行,参数为 false 表示允许正在运行的任务运行完成。Future的 get 方法等待计算完成,获取计算结果。简单的实例代码如下。
1. 单个任务:

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        signalTaskTest();
        Log.d("vae_tag", "after signalTaskTest function");
    }

    private void signalTaskTest() {
        Task.callInBackground(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                /** start test */
                ExecutorService threadPool = Executors.newSingleThreadExecutor();
                Future<String> future = threadPool.submit(new Callable<String>() {
                    public String call() throws Exception {
                        Thread.sleep(2000);
                        return "hello";
                    }
                });
                Log.d("vae_tag", "start waiting result");
                try {
                    Log.d("vae_tag", "get the result " + future.get());
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return null;
            }
        });
    }
}

注:我是在一个线程里面测试 future.get()会等待获取结果(这里有用到Task.callInBackground 在gradle用引入compile ‘com.parse.bolts:bolts-android:1.2.0’)
2. 多个任务:

public class MainActivity extends ActionBarActivity {

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

    private void multipleTasksTest() {
        Task.callInBackground(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                /** start test */
                ExecutorService threadPool2 = Executors.newFixedThreadPool(10);
                CompletionService<Integer> compeletionService = new ExecutorCompletionService<Integer>(
                    threadPool2);
                for (int i = 0; i <= 10; i++) {
                    final int seq = i;
                    compeletionService.submit(new Callable<Integer>() {
                        @Override
                        public Integer call() throws Exception {
                            Thread.sleep(new Random().nextInt(5000));
                            return seq;
                        }
                    });
                }
                for (int i = 0; i < 10; i++) {
                    try {
                        Log.d("vae_tag", "result = " + compeletionService.take().get());
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                return null;
            }
        });
    }
}

配合CompletionService使用。

九,推荐(EventBus 一个可以用于通信的开源库)

github项目地址 https://github.com/greenrobot/EventBus

这个也是我们在应用中经常用到的用于通信的一个类库。特别是在fragment 和fragment,fragment和activity等等之间通信非常的方便,用起来也非常的简单具体的可以去google下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值