緩衝區是一塊特定的內存區域,開闢緩衝區的目的是通過緩存來緩解應用程序上下層之間的性能差異,提高系統性能
漏斗的初始口徑很大,並且擁有一定的容量,因此茶壺中的水可以先倒入漏斗中,就像內存中的數據先寫入一塊緩衝區。只要漏斗夠大,茶壺裏的水很快就能倒完。至此,上層系統完成工作,可以去處理其他業務邏輯。而此時,大部分水在漏斗中,可以有下層系統慢慢處理,直至水完全進入瓶中,漏斗(緩衝區)被清空
基於這種結構,加快了上層組件的處理速度,從而提升了整體性能
緩衝可以協調上層組件和下層組件的性能差,當上曾組建性能優於下層組件時,可以有效減少上層組件對下層組件的等待時間
緩衝最常用的場景就是提高I/O的速度
// 不使用緩衝
writer = new FileWriter(new File("file.text"));
// 使用緩衝
writer = new BufferedWriter(new FileWriter(new File("file.text")));
一般來說,緩衝區不宜過小,過小的緩衝區無法起到真正的緩衝作用,緩衝區也不宜過大,過大的緩衝區會浪費系統能喫,增加GC負擔
另一個典型例子是使用緩衝區提升動畫顯示效果
// 畫一個左右平移的圓球
public class NoBufferMovingCircle extends JApplet implements Runnable {
Image screenImage = null;
Thread thread;
int x = 5;
int move = 1;
@Override
public void init() {
screenImage = createImage(230, 160);
}
@Override
public void start() {
if (thread == null) {
thread = new Thread(this);
thread.start();
}
}
@Override
public void run() {
try {
while (true) {
x += move;
if ((x > 105) || (x < 5)) {
move *= -1;
}
repaint();
Thread.sleep(200);
}
} catch (Exception e) {
}
}
public void drawCircle(Graphics gc) {
Graphics2D g = (Graphics2D)gc;
g.setColor(Color.green);
g.fillRect(0, 0, 200, 100);
g.setColor(Color.red);
g.fillOval(x, 5, 90, 90);
}
@Override
public void paint(Graphics g) { // 畫一個圓,這裏沒有緩衝
g.setColor(Color.white);
g.fillRect(0, 0, 200, 100);
drawCircle(g);
}
}
以上代碼雖然沒有main函數,但是在Eclipse中可以通過Run As下的Java Applet運行(IDEA你看看人家)
此時雖然可以完成平移,但是效果較差,因爲每次的界面刷新都涉及圖片的重新繪製,而這是較爲費時的操作,因此畫面的抖動和白光效果明顯,爲了得到更好的效果可以加上緩衝區
public class BufferMovingCircle extends NoBufferMovingCircle {
Graphics doubleBuffer = null; // 緩衝區
@Override
public void init() {
super.init();
doubleBuffer = screenImage.getGraphics();
}
@Override
public void paint(Graphics g) { // 使用緩衝區,優化原有的paint()方法
doubleBuffer.setColor(Color.white); // 現在內存中畫圖
doubleBuffer.fillRect(0, 0, 200, 100);
drawCircle(doubleBuffer);
g.drawImage(screenImage, 0, 0, this); // 將buffer一次性顯示出來
}
}
除了性能上的優化,緩衝區還可以作爲上層組件和下層組件的一種通訊工具,從而將上層組件和下層組件進行解耦,優化設計模式。在 “生產者消費者模式” 中,連接生產者消費者的緩衝區正是起這個作用