Last active
August 29, 2015 14:04
-
-
Save huangcd/7b4d1f6bf98d46360fbc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
/// <summary> | |
/// http://zrx.zhaojie.me/20140721/ | |
/// 问题在于firstBuffer.Flush的时候会有新的item加到secondBuffer里面,导致一次Flush的时候firstBuffer的元素有可能比secondBuffer的元素少。 | |
/// 解决方法是先把buffer给缓存出去(先缓存secondBuffer再缓存firstBuffer),然后再Flush。 | |
/// </summary> | |
namespace IBufferTest | |
{ | |
public interface IBuffer | |
{ | |
void Cache(); | |
void Flush(); | |
} | |
public class Item | |
{ | |
private bool _doFirst; | |
private readonly int _id; | |
public Item(int id) | |
{ | |
_id = id; | |
} | |
public void First() | |
{ | |
Console.WriteLine(_id + " First"); | |
_doFirst = true; | |
} | |
public void Second() | |
{ | |
Console.WriteLine(_id + " Second"); | |
if (_doFirst) | |
{ | |
return; | |
} | |
throw new Exception(_id + " Should invoke First() first"); | |
} | |
} | |
public class AddBuffer<T> : IBuffer | |
{ | |
private readonly object _gate = new object(); | |
private List<T> _items; | |
private List<T> _toProcess; | |
public int CachedItemCount() | |
{ | |
return _items == null ? 0 : _items.Count; | |
} | |
public void Add(T item) | |
{ | |
lock (_gate) | |
{ | |
if (_items == null) | |
{ | |
_items = new List<T>(); | |
} | |
_items.Add(item); | |
} | |
} | |
public void Cache() | |
{ | |
lock (_gate) | |
{ | |
_toProcess = _items; | |
_items = null; | |
} | |
} | |
public void Flush() | |
{ | |
if (_toProcess == null) | |
{ | |
return; | |
} | |
Process(_toProcess); | |
} | |
protected virtual void Process(List<T> items) { } | |
} | |
public class FirstBuffer : AddBuffer<Item> | |
{ | |
protected override void Process(List<Item> items) | |
{ | |
foreach (var item in items) | |
{ | |
item.First(); | |
} | |
} | |
} | |
public class SecondBuffer : AddBuffer<Item> | |
{ | |
protected override void Process(List<Item> items) | |
{ | |
foreach (var item in items) | |
{ | |
item.Second(); | |
} | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var firstBuffer = new FirstBuffer(); | |
var secondBuffer = new SecondBuffer(); | |
// Thread A | |
new Thread(() => | |
{ | |
var i = 0; | |
while (true) | |
{ | |
var item = new Item(++i); | |
firstBuffer.Add(item); | |
secondBuffer.Add(item); | |
Thread.Sleep(1); | |
} | |
}).Start(); | |
// Thread B | |
new Thread(() => | |
{ | |
while (true) | |
{ | |
secondBuffer.Cache(); | |
firstBuffer.Cache(); | |
firstBuffer.Flush(); | |
secondBuffer.Flush(); | |
Thread.Sleep(100); | |
} | |
}).Start(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment