迅雷2014校招笔试题之多线程编程
来源:互联网 发布:python cookbook 编辑:程序博客网 时间:2024/05/17 07:08
题意:
大体如下: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 exceptione.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 exceptione.printStackTrace();}finally{lock.unlock();}return value;}}
然后在acitivty中启动Producer和Customer两个线程,为了方便,只循环了50次。
package gibbon.thread.threadtestinandroid;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.os.Bundle;import android.os.Handler;import android.os.Handler.Callback;import android.os.Message;import android.R.integer;import android.app.Activity;import android.view.Menu;import android.widget.TextView;public class ConsumerProducerActivity extends Activity {protected static Handler uiHandler;//protected static Handler comsumerHandler;private TextView sizeTextView;private TextView producer_consumer;private ExecutorService executorService;private static String str;private static Buffer buffer = new Buffer();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_consumer_producer);uiHandler = new Handler(new UiHandler());init();}private void init(){sizeTextView = (TextView)findViewById(R.id.size);producer_consumer = (TextView)findViewById(R.id.produce_comsumer);executorService = Executors.newFixedThreadPool(2);executorService.execute(new ProducerTask());executorService.execute(new ComsumerTask());executorService.shutdown();}public static class ProducerTask implements Runnable{@Overridepublic void run(){int count = 50;while(count-- > 0){buffer.write(1000);try {Thread.sleep((int)(Math.random()*10000));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}public static class ComsumerTask implements Runnable{@Overridepublic void run(){int count = 50;int value = 0;while(count-- > 0){buffer.read();try {Thread.sleep((int)(Math.random()*10000));} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.consumer_producer, menu);return true;}public class UiHandler implements Callback{@Overridepublic boolean handleMessage(Message msg) {// TODO Auto-generated method stubsizeTextView.setText("大小为:" + buffer.queue.size());synchronized (msg) {switch (msg.what) {case Definition.Empty:str += Definition.EMPTY_STRING;str += "\n";break;case Definition.FULL:str += Definition.FULL_STRING;str += "\n";break;case Definition.NOTEMPTY:str += Definition.NOTEMPTY_STRING;str += "\n";break;case Definition.NOTFULL:str += Definition.NOTFULL_STRING;str += "\n";break;default:break;}}producer_consumer.setText(str);return false;}}}
另外附带一些自定义变量:
package gibbon.thread.threadtestinandroid;import android.R.integer;public class Definition {protected static final int NOTFULL = 1;protected static final int NOTEMPTY = 2;protected static final int BUFFERSZIE = 3;protected static final int FULL = 4;protected static final int Empty = 5;protected static final String NOTFULL_STRING = "Wait for not noFull condition";protected static final String NOTEMPTY_STRING = "\tWait for notEmpty condition";protected static final String FULL_STRING = "\t\tBufferSize FuLL";protected static final String EMPTY_STRING = "\t\t\tBufferSize Empty";}
运行结果如下:
2 使用ArrayBlockingQueue:
程序如下:
public class ConsumerProducerActivity extends Activity {protected static Handler uiHandler;private TextView sizeTextView;private TextView producer_consumer;private ExecutorService executorService;private static String str;private static Buffer buffer = new Buffer();private static ArrayBlockingQueue<Integer> integer_buffer = new ArrayBlockingQueue<Integer>(10);@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_consumer_producer);uiHandler = new Handler(new UiHandler());init();}private void init(){sizeTextView = (TextView)findViewById(R.id.size);producer_consumer = (TextView)findViewById(R.id.produce_comsumer);executorService = Executors.newFixedThreadPool(2);//executorService.execute(new ProducerTask());//executorService.execute(new ComsumerTask());executorService.execute(new Producer());executorService.execute(new Consumer());executorService.shutdown();}public static class Producer implements Runnable{@Overridepublic void run(){try {int i = 50;while(i-- >0){if(integer_buffer.size() == 10){Message msg = new Message();msg.what = Definition.FULL;uiHandler.sendMessage(msg);}integer_buffer.put(1000);Message msg = new Message();msg.what = Definition.NOTEMPTY;uiHandler.sendMessage(msg);Thread.sleep((int)(Math.random()*10000));}} catch (InterruptedException e) {// TODO: handle exceptione.printStackTrace();}}}public static class Consumer implements Runnable{@Overridepublic void run(){try {int i = 50;while(i-- >0){if(integer_buffer.size() == 0){Message msg = new Message();msg.what = Definition.Empty;uiHandler.sendMessage(msg);}integer_buffer.take();Message msg = new Message();msg.what = Definition.NOTFULL;uiHandler.sendMessage(msg);Thread.sleep((int)(Math.random()*10000));}} catch (InterruptedException e) {// TODO: handle exceptione.printStackTrace();}}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.consumer_producer, menu);return true;}public class UiHandler implements Callback{@Overridepublic boolean handleMessage(Message msg) {// TODO Auto-generated method stubsizeTextView.setText("大小为:" + integer_buffer.size());switch (msg.what) {case Definition.Empty:str += Definition.EMPTY_STRING;str += "\n";break;case Definition.FULL:str += Definition.FULL_STRING;str += "\n";break;case Definition.NOTEMPTY:str += Definition.NOTEMPTY_STRING;str += "\n";break;case Definition.NOTFULL:str += Definition.NOTFULL_STRING;str += "\n";break;default:break;}producer_consumer.setText(str);return false;}}}
这个比较容易理解,因为ArrayBlockingQueue具有能自行实现阻塞队列
PS:转发请注明出处!
- 迅雷2014校招笔试题之多线程编程
- 迅雷2014校招笔试题之多线程编程
- 迅雷2014校招编程题
- 迅雷2014校招编程题
- 迅雷2014校招笔试编程题--求单链表的差集
- 迅雷2014校招笔试编程题——求解两个集合差集,集合是以单向链表存储
- 迅雷2017校招Java笔试题第一题
- 2014--迅雷校招
- 2018校招迅雷测试岗笔试
- 2014 微软校招笔试答案 编程题
- 京东2015校招笔试编程题
- 2016 360校招笔试编程题
- 阿里2018校招笔试编程题
- 2014九月十月百度,迅雷,华为,阿里巴巴,最新校招笔试面试题
- 九月百度,迅雷,华为,阿里巴巴,最新校招笔试面试十题
- 九月百度,迅雷,华为,阿里巴巴,最新校招笔试面试十题 .
- 九月十月百度,迅雷,华为,阿里巴巴最新校招笔试面试三十题(10.16)
- 九月十月百度,迅雷,华为,阿里巴巴最新校招笔试面试三十题(10.18)
- Blocks编程
- 调用者权限与定义者权限的pl/sql子程序
- 男士剧烈运动后应注意
- 文本超长处理
- 【2013快乐男声热门壁纸☆U☆】
- 迅雷2014校招笔试题之多线程编程
- 千兆网口 Freescale ETSEC + Marvell 88E1111 uboot Linux 驱动分析 二
- 织梦DedeCMS模板防盗的四种方法
- 解决xcode5下使用6.1的模拟器提示无法安装的问题
- 设计模式6大原则之开闭原则(Open Close Principle)
- Qt中的相对路径和绝对路径
- UVALive 2930 Minimizing Maximizer(最小区间覆盖数 DP + 线段树优化)
- COM学习笔记
- asp.net实现类似QQ单一账户登录,在另一个地方登录后在原登录窗口提示下线