Android中多线程处理

时间:2022-02-08 23:18:26

     无论如何在Android中都无法避免多线程和并发的操作,并发有可能是app用户请求服务器对服务器来说的并发也有可能是app本身存在多线程并发,今天我们就先从Java基础知识了来学习多线程和并发的操作。


      关于线程Thread和Runnable的基本使用就不多说,我们先介绍下控制线程同步的几种方法:

     (1)使用synchronized修饰方法、代码块,方法中的变量。

     (2)使用volatile修饰成员变量。

     (3)使用阻塞队列---BlockingQueue实现同步。

      本部分就介绍BlockingQueue的使用。

      首先BoockingQueue是一个接口,它有四个实现子类,分别是:

       (1)ArrayBlockingQueue:规定大小的BlockingQueue,在创建时,构造函数必须制定int类型的大小,它遵循FIFO的原则。

       (2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的。

       (3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.

       (4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.

       下面先给出一个ArrayBlockingQueue的使用实例:

       

/** 创建10个Runnable的Blocking队列 */
private static BlockingQueue<Runnable> mArrayBlockQueue = new ArrayBlockingQueue<Runnable>(
10);

    /**
     * 一个测试用到的线程
     *
     * @author Administrator
     *
     */
    private static class BlockThread implements Runnable {
        String name;

        public BlockThread(String name) {
            this.name = name;
        }
        public void run() {
            System.out.println("--->" + name);
        }
    }


    /**
     * 初始化mArrayBlockQueue队列
     */
    private static void initArrayBlockQueue() {
        for (int i = 0; i < 10; i++) {
            BlockThread block = new BlockThread("张三" + i);
            boolean boo = mArrayBlockQueue.add(block);
            System.out.println(boo);
        }
    }
//最后在main()方法中使用队列,遍历取出所有的Runnable
    public static void main(String[] args) {
        initArrayBlockQueue();
        System.out.println("线程大小:" + mArrayBlockQueue.size());
        // 遍历取出队列中的Runnable
        for (int i = 0; i < mArrayBlockQueue.size(); i++) {
            try {
                mArrayBlockQueue.take().run();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }


      上面是一个 ArrayBlockingQueue队列的简单使用,我们应该注意的是在创建 ArrayBlockingQueue对象的时候指定了其大小为10,在初始化(存入Runnable对象的时候)时调用了其add()方法,并且在取出时调用了take()方法,其实BlockingQueue提供了多种方法存入和取出数据。下面详细介绍下这些方法:

      (1)add(object):添加一个对象到BlockingQueue,如果添加成功就返回true,如果添加不成功(比如添加的内容超过其容量)则会直接抛出异常导致程序崩溃。

      (2)offer(object):添加一个对象到BlockingQueue,如果添加成功就返回false,如果添加失败就返回false,无论如何也不会抛出异常,即使添加失败程序也运行正常。

      (3)take():取走BlockingQueue里排在首位的对象,BlockingQueue为空,阻断进入等待状态直到Blocking有新的对象被加入为止

      (4)peek():从BlockingQueue取出一个值,但是不删除,因此每次获取都是第一个元素。

      (5)poll():从BlockingQueue取出一个值,同时删除该元素。

Android中多线程处理

         实际上,查看源码我们会发现,add()方法实际上是调用了offer()方法,而offer()和put()都最终都调用了insert()方法,然后将对象保存在一个Object数组中。

       BlockingQueue是一个接口,他有四个实现类,下面分别介绍:   

      1) ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入      先出)顺序排序的.

      2) LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的

      3) PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.

      4) SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的.

      说到这里,那么BlockingQueue在什么地方用呢?通常我们用在多线程同步控制上,如果有很多线程需要其同步执行,那么使用BlockingQueue是再适合不过的了。

       此外,使用阻塞队列也是实现生产--消费者机制的很好的一个案例,测试代码如下:

      

private static BlockingQueue<String> as = new ArrayBlockingQueue<String>(20);
public static void main(String[] args) {
// 先消费,发现没有就会阻塞,知道生产者生产了对象
customer();
// 生产
producter();
}

/**
* 生产者
*/
private static void producter() {
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (true) {
i++;
try {
// 每隔1秒生产一个对象
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
as.add("哈哈-->" + i);
if (i >= 10) {
System.out.println("队列大小为:" + as.size());
break;
}
}
}
}).start();
}

/**
* 消费者
*/
private static void customer() {
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println(as.take());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}