双线程-生产者与消费者问题

  之前做下载程序的时候没有注意过效率,在这个靠硬件来拉开用户体验的时代应用程序内算法效率很容易被忽视。

  以前的思路是用 inputstream 来down数据,存到 byte[] 中直接写到文件中。

  后来重温编程之美的时候看到了类似的文章。如果要提高下载效率,需要把写文件和读文件分开,一个线程负责读数据,另一个线程负责写数据,数据池一定要用线程安全的数据结构。

 

     ***********************************************我是下载和Surfaceview的分割线***************************************************

  

   在用SurfaceView做动画的时候也是同样的道理,如果读出一张Bitmap再去显示,界面肯定会卡。

  需要使用双缓冲,开辟两个线程,一个用来读图,一个用来显示。

  下面是示例代码:

  

  1 package com.testSurfaceView;
  2 
  3 import java.lang.reflect.Field;
  4 import java.util.ArrayList;
  5 import android.app.Activity;
  6 import android.graphics.Bitmap;
  7 import android.graphics.BitmapFactory;
  8 import android.graphics.Canvas;
  9 import android.graphics.Paint;
 10 import android.graphics.Rect;
 11 import android.os.Bundle;
 12 import android.util.Log;
 13 import android.view.SurfaceHolder;
 14 import android.view.SurfaceView;
 15 import android.view.View;
 16 import android.widget.Button;
 17 
 18 public class TestSurfaceView extends Activity {
 19     /** Called when the activity is first created. */
 20     Button btnSingleThread, btnDoubleThread;
 21     SurfaceView sfv;
 22     SurfaceHolder sfh;
 23     ArrayList<Integer> imgList = new ArrayList<Integer>();
 24     int imgWidth, imgHeight;
 25     Bitmap bitmap;//独立线程读取,独立线程绘图
 26 
 27     @Override
 28     public void onCreate(Bundle savedInstanceState) {
 29         super.onCreate(savedInstanceState);
 30         setContentView(R.layout.main);
 31 
 32         btnSingleThread = (Button) this.findViewById(R.id.Button01);
 33         btnDoubleThread = (Button) this.findViewById(R.id.Button02);
 34         btnSingleThread.setOnClickListener(new ClickEvent());
 35         btnDoubleThread.setOnClickListener(new ClickEvent());
 36         sfv = (SurfaceView) this.findViewById(R.id.SurfaceView01);
 37         sfh = sfv.getHolder();
 38         sfh.addCallback(new MyCallBack());// 自动运行surfaceCreated以及surfaceChanged
 39     }
 40 
 41     class ClickEvent implements View.OnClickListener {
 42 
 43         @Override
 44         public void onClick(View v) {
 45 
 46             if (v == btnSingleThread) {
 47                 new Load_DrawImage(0, 0).start();//开一条线程读取并绘图
 48             } else if (v == btnDoubleThread) {
 49                 new LoadImage().start();//开一条线程读取
 50                 new DrawImage(imgWidth + 10, 0).start();//开一条线程绘图
 51             }
 52 
 53         }
 54 
 55     }
 56 
 57     class MyCallBack implements SurfaceHolder.Callback {
 58 
 59         @Override
 60         public void surfaceChanged(SurfaceHolder holder, int format, int width,
 61                 int height) {
 62             Log.i("Surface:", "Change");
 63 
 64         }
 65 
 66         @Override
 67         public void surfaceCreated(SurfaceHolder holder) {
 68             Log.i("Surface:", "Create");
 69 
 70             // 用反射机制来获取资源中的图片ID和尺寸
 71             Field[] fields = R.drawable.class.getDeclaredFields();
 72             for (Field field : fields) {
 73                 if (!"icon".equals(field.getName()))// 除了icon之外的图片
 74                 {
 75                     int index = 0;
 76                     try {
 77                         index = field.getInt(R.drawable.class);
 78                     } catch (IllegalArgumentException e) {
 79                         // TODO Auto-generated catch block
 80                         e.printStackTrace();
 81                     } catch (IllegalAccessException e) {
 82                         // TODO Auto-generated catch block
 83                         e.printStackTrace();
 84                     }
 85                     // 保存图片ID
 86                     imgList.add(index);
 87                 }
 88             }
 89             // 取得图像大小
 90             Bitmap bmImg = BitmapFactory.decodeResource(getResources(),
 91                     imgList.get(0));
 92             imgWidth = bmImg.getWidth();
 93             imgHeight = bmImg.getHeight();
 94         }
 95 
 96         @Override
 97         public void surfaceDestroyed(SurfaceHolder holder) {
 98             Log.i("Surface:", "Destroy");
 99 
100         }
101 
102     }
103 
104     /**
105      * 读取并显示图片的线程
106      */
107     class Load_DrawImage extends Thread {
108         int x, y;
109         int imgIndex = 0;
110 
111         public Load_DrawImage(int x, int y) {
112             this.x = x;
113             this.y = y;
114         }
115 
116         public void run() {
117             while (true) {
118                 Canvas c = sfh.lockCanvas(new Rect(this.x, this.y, this.x
119                         + imgWidth, this.y + imgHeight));
120                 Bitmap bmImg = BitmapFactory.decodeResource(getResources(),
121                         imgList.get(imgIndex));
122                 c.drawBitmap(bmImg, this.x, this.y, new Paint());
123                 imgIndex++;
124                 if (imgIndex == imgList.size())
125                     imgIndex = 0;
126 
127                 sfh.unlockCanvasAndPost(c);// 更新屏幕显示内容
128             }
129         }
130     };
131 
132     /**
133      * 只负责绘图的线程
134      */
135     class DrawImage extends Thread {
136         int x, y;
137 
138         public DrawImage(int x, int y) {
139             this.x = x;
140             this.y = y;
141         }
142 
143         public void run() {
144             while (true) {
145                 if (bitmap != null) {//如果图像有效
146                     Canvas c = sfh.lockCanvas(new Rect(this.x, this.y, this.x
147                             + imgWidth, this.y + imgHeight));
148 
149                     c.drawBitmap(bitmap, this.x, this.y, new Paint());
150 
151                     sfh.unlockCanvasAndPost(c);// 更新屏幕显示内容
152                 }
153             }
154         }
155     };
156 
157     /**
158      * 只负责读取图片的线程
159      */
160     class LoadImage extends Thread {
161         int imgIndex = 0;
162 
163         public void run() {
164             while (true) {
165                 bitmap = BitmapFactory.decodeResource(getResources(),
166                         imgList.get(imgIndex));
167                 imgIndex++;
168                 if (imgIndex == imgList.size())//如果到尽头则重新读取
169                     imgIndex = 0;
170             }
171         }
172     };
173 }
posted on 2012-06-17 21:34  逝姿飞鱼 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lovebigpizza/archive/2012/06/17/2552875.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个用 Java 实现的生产者消费者模式的缓存延迟删例子: ```java import java.util.LinkedList; public class ProducerConsumerExample { public static void main(String[] args) { final PC pc = new PC(); // 创建一个生产者线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { try { pc.produce(); } catch (InterruptedException e) { e.printStackTrace(); } } }); // 创建一个消费者线程 Thread t2 = new Thread(new Runnable() { @Override public void run() { try { pc.consume(); } catch (InterruptedException e) { e.printStackTrace(); } } }); // 启动线程 t1.start(); t2.start(); // 等待线程结束 try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } } // 生产者消费者共享的缓存区 public static class PC { LinkedList<Integer> list = new LinkedList<>(); int capacity = 1; // 生产者方法 public void produce() throws InterruptedException { int value = 0; while (true) { synchronized (this) { // 如果缓存区已满,则等待 while (list.size() == capacity) { wait(); } System.out.println("Producer produced-" + value); // 将值添加到缓存区 list.add(value++); // 唤醒消费者线程 notify(); // 等待一段时间,模拟生产延迟 Thread.sleep(1000); } } } // 消费者方法 public void consume() throws InterruptedException { while (true) { synchronized (this) { // 如果缓存区为空,则等待 while (list.size() == 0) { wait(); } // 从缓存区取出值 int val = list.removeFirst(); System.out.println("Consumer consumed-" + val); // 唤醒生产者线程 notify(); // 等待一段时间,模拟消费延迟 Thread.sleep(1000); // 再次检查缓存区是否为空,如果为空则删除缓存区 if (list.size() == 0) { list = null; break; } } } } } } ``` 这个例子中,我们使用了一个 LinkedList 作为生产者消费者共享的缓存区,生产者线程不断向缓存区中添加值,消费者线程不断从缓存区中取出值。当缓存区已满时,生产者线程会等待,当缓存区为空时,消费者线程会等待。为了模拟生产和消费的延迟,我们在生产者消费者方法中都加入了 Thread.sleep() 方法。此外,我们还加入了一个删机制,当缓存区为空时,消费者线程会将缓存区删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值