歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

迅雷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="http://schemas.android.com/apk/res/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;
 }
}

相關閱讀:迅雷2014校園招聘筆試題  http://www.linuxidc.com/Linux/2013-09/90491.htm

更多詳情請繼續閱讀第2頁的內容: http://www.linuxidc.com/Linux/2013-09/90716p2.htm

Copyright © Linux教程網 All Rights Reserved