Skip to content

Instantly share code, notes, and snippets.

@huangcd
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huangcd/7b4d1f6bf98d46360fbc to your computer and use it in GitHub Desktop.
Save huangcd/7b4d1f6bf98d46360fbc to your computer and use it in GitHub Desktop.
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