歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 迅雷2014校招筆試題之多線程編程

迅雷2014校招筆試題之多線程編程

日期:2017/3/1 9:52:45   编辑:Linux編程

題意:

大體如下: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