迅雷2014校招笔试题之多线程编程

大体如下:Android中Activity开启两个线程,一个Produce线程,一个Customer线程,共享Integer[10]数组,Produce线程不断向数组中写入1000,写满后等待,Customer线程不断清空数组内容,当数组全被清空后,通知Produce线程写入数据,Activity要及时刷新当前Integer数组内容size。

分析:

从题意可知,在Java方面,这里涉及到两个线程共享一个数组,也就是说当一个线程在运行操作数组时,另一个线程只能等待,否则将出现竞争状态,即一个线程在运行时,另一个线程只能处于阻塞状态。在Andriod方面,因为在Acitivty中要及时刷新当前Integer数组的内容size,所以在UI主线程中要实时读取Integer的size,这个读取是在主线程完成的,而两个子线程可以把改变的信息通过handler发送到主线程,进而主线程进行解析信息,根据信息显示。

实现:

分两种方法实现,一种为比较旧的版本,用到了java旧版本的监听器,另一种使用较新版本的类,这些类内部具有阻塞功能,三个具体的阻塞队列为:ArrayBlockingQueue,  LinkBlockingQueue和PriorityBlockingQueue。它们都在java.util.concurrent的包中。其中,ArrayBlockingQueue使用数组实现阻塞队列。LinkBlockingQueue使用链表实现阻塞队列。

1 利用监听器(monitor)对象:

在activity的xml布局中定义了两个TextView,分别用来显示实时数组大小和写入清楚情况:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android=""
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
   
    <TextView
        android:id = "@+id/size"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:textSize="20.0sp"
  android:padding="5dp"
 />
   
  <ScrollView 
        android:id="@+id/scrollView01" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent">
    <TextView
        android:id="@+id/produce_comsumer"
        android:gravity="center_vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />
  </ScrollView>
</LinearLayout>

定义了一个类Buffer,完成包括write(写入方法)和read(清除方法)。程序中生成了两个状态,分别为notFull和notEmpty,作用具体看程序注解。而uiHandler主要用于主线程和子线程的消息通信。当子线程发生变化之后,通过sendMessage方法发生消息,然后主线程通过CallBack得到Message

package gibbon.thread.threadtestinandroid;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import android.R.integer;
import android.os.Message;

public class Buffer {
 private static Lock lock = new ReentrantLock();
 private static Condition notEmpty = lock.newCondition();
 private static Condition notFull = lock.newCondition();
 private static final int CAPACITY = 10;
 
 protected LinkedList<Integer> queue = new LinkedList<Integer>();
 
 protected void write(int value){
  lock.lock();
  try {
   if(queue.size() == CAPACITY){
    System.out.println("Wait for not noFull condition");
    Message msg = new Message();
    msg.what = Definition.FULL;
    ConsumerProducerActivity.uiHandler.sendMessage(msg);
    notFull.await(); //因为已经满了,所以notFull必须等待,等取走数据才能继续运行(即只能等待下面的数据取走,然后调用signal唤醒)
   }
   
   queue.offer(value);
   Message msg = new Message();
   msg.what = Definition.NOTEMPTY;
   ConsumerProducerActivity.uiHandler.sendMessage(msg);
   notEmpty.signal(); //因为非空,所以唤醒非空功能
  } catch (InterruptedException e) {
   // TODO: handle exception
   e.printStackTrace();
  }finally{
   lock.unlock();
  }
 }
 
 protected int read(){
  lock.lock();
  int value = 0;
  try {
   if(queue.size() == 0){
    System.out.println("\t\tWait for notEmpty condition");
    Message msg = new Message();
    msg.what = Definition.Empty;
    ConsumerProducerActivity.uiHandler.sendMessage(msg); //这里的Message对象在线程中只能多次创建,若不这样,
          //则如在主线程用到了该对象的同时,下面的线程又进行了修改,则就发生变化
    notEmpty.await(); //这里就可以等待上面的数据写入之后,通过notEmpty来唤醒
   }
   
   value = queue.remove();
   Message msg = new Message();
   msg.what = Definition.NOTEMPTY;
   ConsumerProducerActivity.uiHandler.sendMessage(msg);
   notFull.signal(); //取走数据了,换新上面的notFull等待
  } catch (InterruptedException e) {
   // TODO: handle exception
   e.printStackTrace();
  }finally{
   lock.unlock();
  }
  return value;
 }
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/33037b39459f71be03749d27d176fd8a.html