迅雷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,分别用来显示实时数组大小和写入清楚情况:
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具有能自行实现阻塞队列