迅雷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,分别用来显示实时数组大小和写入清楚情况:

[html]  view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:orientation="vertical"  
  6.     >  
  7.       
  8.     <TextView   
  9.         android:id = "@+id/size"  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:textSize="20.0sp"  
  13.         android:padding="5dp"  
  14.     />  
  15.       
  16.      <ScrollView     
  17.         android:id="@+id/scrollView01"    
  18.         android:layout_width="fill_parent"    
  19.         android:layout_height="fill_parent">   
  20.         <TextView   
  21.             android:id="@+id/produce_comsumer"  
  22.             android:gravity="center_vertical"  
  23.             android:layout_width="fill_parent"  
  24.             android:layout_height="wrap_content"  
  25.             />  
  26.      </ScrollView>   
  27. </LinearLayout>  
  28.    

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

[java]  view plain copy
  1. package gibbon.thread.threadtestinandroid;  
  2.   
  3. import java.util.LinkedList;  
  4. import java.util.concurrent.locks.Condition;  
  5. import java.util.concurrent.locks.Lock;  
  6. import java.util.concurrent.locks.ReentrantLock;  
  7.   
  8. import android.R.integer;  
  9. import android.os.Message;  
  10.   
  11. public class Buffer {  
  12.     private static Lock lock = new ReentrantLock();  
  13.     private static Condition notEmpty = lock.newCondition();  
  14.     private static Condition notFull = lock.newCondition();  
  15.     private static final int CAPACITY = 10;  
  16.       
  17.     protected LinkedList<Integer> queue = new LinkedList<Integer>();  
  18.       
  19.     protected void write(int value){  
  20.         lock.lock();  
  21.         try {  
  22.             if(queue.size() == CAPACITY){  
  23.                 System.out.println("Wait for not noFull condition");  
  24.                 Message msg = new Message();  
  25.                 msg.what = Definition.FULL;  
  26.                 ConsumerProducerActivity.uiHandler.sendMessage(msg);  
  27.                 notFull.await(); //因为已经满了,所以notFull必须等待,等取走数据才能继续运行(即只能等待下面的数据取走,然后调用signal唤醒)  
  28.             }  
  29.               
  30.             queue.offer(value);  
  31.             Message msg = new Message();  
  32.             msg.what = Definition.NOTEMPTY;  
  33.             ConsumerProducerActivity.uiHandler.sendMessage(msg);  
  34.             notEmpty.signal(); //因为非空,所以唤醒非空功能  
  35.         } catch (InterruptedException e) {  
  36.             // TODO: handle exception  
  37.             e.printStackTrace();  
  38.         }finally{  
  39.             lock.unlock();  
  40.         }  
  41.     }  
  42.       
  43.     protected int read(){  
  44.         lock.lock();  
  45.         int value = 0;  
  46.         try {  
  47.             if(queue.size() == 0){  
  48.                 System.out.println("\t\tWait for notEmpty condition");  
  49.                 Message msg = new Message();  
  50.                 msg.what = Definition.Empty;  
  51.                 ConsumerProducerActivity.uiHandler.sendMessage(msg); //这里的Message对象在线程中只能多次创建,若不这样,  
  52.                                         //则如在主线程用到了该对象的同时,下面的线程又进行了修改,则就发生变化  
  53.                 notEmpty.await(); //这里就可以等待上面的数据写入之后,通过notEmpty来唤醒  
  54.             }  
  55.               
  56.             value = queue.remove();  
  57.             Message msg = new Message();  
  58.             msg.what = Definition.NOTEMPTY;  
  59.             ConsumerProducerActivity.uiHandler.sendMessage(msg);  
  60.             notFull.signal(); //取走数据了,换新上面的notFull等待  
  61.         } catch (InterruptedException e) {  
  62.             // TODO: handle exception  
  63.             e.printStackTrace();  
  64.         }finally{  
  65.             lock.unlock();  
  66.         }  
  67.         return value;  
  68.     }  
  69. }  

然后在acitivty中启动Producer和Customer两个线程,为了方便,只循环了50次。

[java]  view plain copy
  1. package gibbon.thread.threadtestinandroid;  
  2.   
  3. import java.util.concurrent.ExecutorService;  
  4. import java.util.concurrent.Executors;  
  5.   
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.os.Handler.Callback;  
  9. import android.os.Message;  
  10. import android.R.integer;  
  11. import android.app.Activity;  
  12. import android.view.Menu;  
  13. import android.widget.TextView;  
  14.   
  15. public class ConsumerProducerActivity extends Activity {  
  16.     protected static Handler uiHandler;  
  17.     //protected static Handler comsumerHandler;  
  18.     private TextView sizeTextView;  
  19.     private TextView producer_consumer;  
  20.     private ExecutorService executorService;  
  21.     private static String str;  
  22.     private static Buffer buffer = new Buffer();  
  23.       
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.activity_consumer_producer);  
  28.   
  29.         uiHandler = new Handler(new UiHandler());  
  30.         init();   
  31.     }  
  32.   
  33.     private void init(){  
  34.         sizeTextView = (TextView)findViewById(R.id.size);  
  35.         producer_consumer = (TextView)findViewById(R.id.produce_comsumer);  
  36.           
  37.         executorService = Executors.newFixedThreadPool(2);  
  38.         executorService.execute(new ProducerTask());  
  39.         executorService.execute(new ComsumerTask());  
  40.         executorService.shutdown();  
  41.     }  
  42.       
  43.     public static class ProducerTask implements Runnable{  
  44.         @Override  
  45.         public void run(){  
  46.             int count = 50;  
  47.             while(count-- > 0){  
  48.                 buffer.write(1000);  
  49.                 try {  
  50.                     Thread.sleep((int)(Math.random()*10000));  
  51.                 } catch (InterruptedException e) {  
  52.                     // TODO Auto-generated catch block  
  53.                     e.printStackTrace();  
  54.                 }  
  55.             }  
  56.         }  
  57.     }  
  58.       
  59.     public static class ComsumerTask implements Runnable{  
  60.         @Override  
  61.         public void run(){  
  62.             int count = 50;  
  63.             int value = 0;  
  64.             while(count-- > 0){  
  65.                 buffer.read();  
  66.                 try {  
  67.                     Thread.sleep((int)(Math.random()*10000));  
  68.                 } catch (InterruptedException e) {  
  69.                     // TODO Auto-generated catch block  
  70.                     e.printStackTrace();  
  71.                 }  
  72.             }  
  73.         }  
  74.     }  
  75.       
  76.     @Override  
  77.     public boolean onCreateOptionsMenu(Menu menu) {  
  78.         // Inflate the menu; this adds items to the action bar if it is present.  
  79.         getMenuInflater().inflate(R.menu.consumer_producer, menu);  
  80.         return true;  
  81.     }  
  82.       
  83.     public class UiHandler implements Callback{  
  84.   
  85.         @Override  
  86.         public boolean handleMessage(Message msg) {  
  87.             // TODO Auto-generated method stub  
  88.             sizeTextView.setText("大小为:" + buffer.queue.size());  
  89.             synchronized (msg) {  
  90.                 switch (msg.what) {  
  91.                 case Definition.Empty:  
  92.                     str += Definition.EMPTY_STRING;  
  93.                     str += "\n";  
  94.                     break;  
  95.                 case Definition.FULL:  
  96.                     str += Definition.FULL_STRING;  
  97.                     str += "\n";  
  98.                     break;  
  99.                 case Definition.NOTEMPTY:  
  100.                     str += Definition.NOTEMPTY_STRING;  
  101.                     str += "\n";  
  102.                     break;  
  103.                 case Definition.NOTFULL:  
  104.                     str += Definition.NOTFULL_STRING;  
  105.                     str += "\n";  
  106.                     break;  
  107.                 default:  
  108.                     break;  
  109.                 }  
  110.             }  
  111.             producer_consumer.setText(str);  
  112.             return false;  
  113.         }  
  114.           
  115.     }  
  116.   
  117. }  

另外附带一些自定义变量:

[java]  view plain copy
  1. package gibbon.thread.threadtestinandroid;  
  2.   
  3. import android.R.integer;  
  4.   
  5. public class Definition {  
  6.     protected static final int NOTFULL = 1;  
  7.     protected static final int NOTEMPTY = 2;  
  8.     protected static final int BUFFERSZIE = 3;  
  9.     protected static final int FULL = 4;  
  10.     protected static final int Empty = 5;  
  11.     protected static final String NOTFULL_STRING = "Wait for not noFull condition";  
  12.     protected static final String NOTEMPTY_STRING = "\tWait for notEmpty condition";  
  13.     protected static final String FULL_STRING = "\t\tBufferSize FuLL";  
  14.     protected static final String EMPTY_STRING = "\t\t\tBufferSize Empty";  
  15. }  

运行结果如下:


2 使用ArrayBlockingQueue:

程序如下:

[java]  view plain copy
  1. public class ConsumerProducerActivity extends Activity {  
  2.     protected static Handler uiHandler;  
  3.     private TextView sizeTextView;  
  4.     private TextView producer_consumer;  
  5.     private ExecutorService executorService;  
  6.     private static String str;  
  7.     private static Buffer buffer = new Buffer();  
  8.     private static ArrayBlockingQueue<Integer> integer_buffer = new ArrayBlockingQueue<Integer>(10);  
  9.       
  10.     @Override  
  11.     protected void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.activity_consumer_producer);  
  14.   
  15.         uiHandler = new Handler(new UiHandler());  
  16.         init();   
  17.     }  
  18.   
  19.     private void init(){  
  20.         sizeTextView = (TextView)findViewById(R.id.size);  
  21.         producer_consumer = (TextView)findViewById(R.id.produce_comsumer);  
  22.           
  23.         executorService = Executors.newFixedThreadPool(2);  
  24.         //executorService.execute(new ProducerTask());  
  25.         //executorService.execute(new ComsumerTask());  
  26.         executorService.execute(new Producer());  
  27.         executorService.execute(new Consumer());  
  28.         executorService.shutdown();  
  29.     }  
  30. public static class Producer implements Runnable{  
  31.         @Override  
  32.         public void run(){  
  33.             try {  
  34.                 int i = 50;  
  35.                 while(i-- >0){  
  36.                     if(integer_buffer.size() == 10){  
  37.                         Message msg = new Message();  
  38.                         msg.what = Definition.FULL;  
  39.                         uiHandler.sendMessage(msg);  
  40.                     }  
  41.                     integer_buffer.put(1000);  
  42.                     Message msg = new Message();  
  43.                     msg.what = Definition.NOTEMPTY;  
  44.                     uiHandler.sendMessage(msg);  
  45.                     Thread.sleep((int)(Math.random()*10000));  
  46.                 }  
  47.             } catch (InterruptedException e) {  
  48.                 // TODO: handle exception  
  49.                 e.printStackTrace();  
  50.             }  
  51.         }  
  52.     }  
  53.       
  54.     public static class Consumer implements Runnable{  
  55.         @Override  
  56.         public void run(){  
  57.             try {  
  58.                 int i = 50;  
  59.                 while(i-- >0){  
  60.                     if(integer_buffer.size() == 0){  
  61.                         Message msg = new Message();  
  62.                         msg.what = Definition.Empty;  
  63.                         uiHandler.sendMessage(msg);  
  64.                     }  
  65.                     integer_buffer.take();  
  66.                     Message msg = new Message();  
  67.                     msg.what = Definition.NOTFULL;  
  68.                     uiHandler.sendMessage(msg);  
  69.                     Thread.sleep((int)(Math.random()*10000));  
  70.                 }  
  71.             } catch (InterruptedException e) {  
  72.                 // TODO: handle exception  
  73.                 e.printStackTrace();  
  74.             }  
  75.         }  
  76.     }  
  77.       
  78.     @Override  
  79.     public boolean onCreateOptionsMenu(Menu menu) {  
  80.         // Inflate the menu; this adds items to the action bar if it is present.  
  81.         getMenuInflater().inflate(R.menu.consumer_producer, menu);  
  82.         return true;  
  83.     }  
  84.       
  85.     public class UiHandler implements Callback{  
  86.   
  87.         @Override  
  88.         public boolean handleMessage(Message msg) {  
  89.             // TODO Auto-generated method stub  
  90.             sizeTextView.setText("大小为:" + integer_buffer.size());  
  91.             switch (msg.what) {  
  92.             case Definition.Empty:  
  93.                 str += Definition.EMPTY_STRING;  
  94.                 str += "\n";  
  95.                 break;  
  96.             case Definition.FULL:  
  97.                 str += Definition.FULL_STRING;  
  98.                 str += "\n";  
  99.                 break;  
  100.             case Definition.NOTEMPTY:  
  101.                 str += Definition.NOTEMPTY_STRING;  
  102.                 str += "\n";  
  103.                 break;  
  104.             case Definition.NOTFULL:  
  105.                 str += Definition.NOTFULL_STRING;  
  106.                 str += "\n";  
  107.                 break;  
  108.             default:  
  109.                 break;  
  110.             }  
  111.   
  112.             producer_consumer.setText(str);  
  113.             return false;  
  114.         }  
  115.           
  116.     }  
  117. }  

这个比较容易理解,因为ArrayBlockingQueue具有能自行实现阻塞队列




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值