C\#유일한 검사 요청
네트워크 요청 에서 보 내 는 요청 이 자주 발생 합 니 다.서버 응답 은 성공 적 이지 만 돌아 올 때 네트워크 고장 이 발생 하여 클 라 이언 트 가 요청 결 과 를 받 지 못 하면 클 라 이언 트 프로그램 은 네트워크 고장 으로 판단 하고 같은 요청 을 반복 적 으로 보 낼 수 있 습 니 다.물론 인터페이스 에서 요청 결과 조회 인 터 페 이 스 를 정의 한다 면 이런 중복 은 상대 적 으로 적 을 것 이다.특히 거래 류 의 데 이 터 는 중복 전송 요청 을 피해 야 한다.또 다른 상황 은 사용자 가 인터페이스 단 추 를 너무 빨리 클릭 하여 똑 같은 내용 의 요청 이 발생 하면 백 엔 드 도 여과 해 야 한 다 는 것 이다.이런 것 은 보통 시스템 도 킹 에 나타 나 제3자 시스템 의 업무 논 리 를 제어 할 수 없고 자신의 업무 논리 에서 한정 해 야 한다.
기타 필요 설명:
이러한 요 구 는 일반적으로 시간 범위 와 높 은 병발 의 특징 이 존재 하 는데 짧 은 시간 안에 중복 되 는 요구 가 발생 하기 때문에 모듈 에 대해 높 은 병발 성 을 지원 해 야 한다.
기술 실현:
요청 한 업무 내용 에 대해 MD5 요약 을 하고 MD5 요약 을 캐 시 에 저장 하 며 모든 요청 데 이 터 는 이 공공 호출 방법 을 통 해 판단 합 니 다.
코드 구현:
공공 호출 코드 유 니 크 체크 는 단일 모드 로 유일한 대상 을 만 들 고 다 중 스 레 드 호출 시 하나의 통 일 된 캐 시 라 이브 러 리 만 방문 할 수 있 습 니 다.
/*
* volatile const ,volatile (type specifier)。
* 。
* volatile, : , 。
*/
private static readonly object lockHelper = new object();
private volatile static UniqueCheck _instance;
/// <summary>
///
/// </summary>
/// <returns></returns>
public static UniqueCheck GetInstance()
{
if (_instance == null)
{
lock (lockHelper)
{
if (_instance == null)
_instance = new UniqueCheck();
}
}
return _instance;
}
volatile 의 수정자 에 주의해 야 합 니 다.실제 테스트 과정 에서 이 수정자 가 없 으 면 높 은 병발 상황 에서 오류 가 발생 할 수 있 습 니 다.동시 처리 대기 열 을 사용자 정의 합 니 다.코드 는 다음 과 같 습 니 다:ConcurrentLinkedQueue
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace PackgeUniqueCheck
{
/// <summary>
/// , 100
/// </summary>
/// <typeparam name="T"></typeparam>
public class ConcurrentLinkedQueue<T>
{
private class Node<K>
{
internal K Item;
internal Node<K> Next;
public Node(K item, Node<K> next)
{
this.Item = item;
this.Next = next;
}
}
private Node<T> _head;
private Node<T> _tail;
public ConcurrentLinkedQueue()
{
_head = new Node<T>(default(T), null);
_tail = _head;
}
public bool IsEmpty
{
get { return (_head.Next == null); }
}
/// <summary>
///
/// </summary>
/// <param name="item"></param>
public void Enqueue(T item)
{
Node<T> newNode = new Node<T>(item, null);
while (true)
{
Node<T> curTail = _tail;
Node<T> residue = curTail.Next;
// _tail process
if (curTail == _tail)
{
//A process C ,_tail
if (residue == null)
{
//C process tail , tail
if (Interlocked.CompareExchange<Node<T>>(
ref curTail.Next, newNode, residue) == residue)
{
//D tail
Interlocked.CompareExchange<Node<T>>(ref _tail, newNode, curTail);
return;
}
}
else
{
//B D
Interlocked.CompareExchange<Node<T>>(ref _tail, residue, curTail);
}
}
}
}
/// <summary>
///
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public bool TryDequeue(out T result)
{
Node<T> curHead;
Node<T> curTail;
Node<T> next;
while (true)
{
curHead = _head;
curTail = _tail;
next = curHead.Next;
if (curHead == _head)
{
if (next == null) //Queue
{
result = default(T);
return false;
}
if (curHead == curTail) //Queue Enqueue node
{
// Process
Interlocked.CompareExchange<Node<T>>(ref _tail, next, curTail);
}
else
{
// next.Item CAS
result = next.Item;
// _head , _head next
if (Interlocked.CompareExchange<Node<T>>(ref _head,
next, curHead) == curHead)
break;
}
}
}
return true;
}
/// <summary>
///
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public bool TryGetTail(out T result)
{
result = default(T);
if (_tail == null)
{
return false;
}
result = _tail.Item;
return true;
}
}
}
매우 간단 한 유일한 검사 논리 이지 만 효율 적 이 고 병행 지원 이 높 으 며 신뢰성 이 높 으 며 메모리 사용량 이 적 으 려 면 이러한 수 요 를 실현 하고 세밀 한 시 뮬 레이 션 테스트 를 해 야 한다.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Collections;
namespace PackgeUniqueCheck
{
public class UniqueCheck
{
/*
* volatile const ,volatile (type specifier)。
* 。
* volatile, : , 。
*/
private static readonly object lockHelper = new object();
private volatile static UniqueCheck _instance;
/// <summary>
///
/// </summary>
/// <returns></returns>
public static UniqueCheck GetInstance()
{
if (_instance == null)
{
lock (lockHelper)
{
if (_instance == null)
_instance = new UniqueCheck();
}
}
return _instance;
}
private UniqueCheck()
{
// ,
_DataKey = Hashtable.Synchronized(new Hashtable());
Queue myqueue = new Queue();
_DataQueue = Queue.Synchronized(myqueue);
_Myqueue = new ConcurrentLinkedQueue<string>();
_Timer = new Thread(DoTicket);
_Timer.Start();
}
#region
/// <summary>
/// : 1
/// :1-7200000, 1 2
/// </summary>
/// <param name="value"></param>
public void SetTimeSpan(int value)
{
if (value > 0&& value <=7200000)
{
_TimeSpan = value;
}
}
/// <summary>
/// Cache
/// :1-5000000,1 500
/// </summary>
/// <param name="value"></param>
public void SetCacheMaxNum(int value)
{
if (value > 0 && value <= 5000000)
{
_CacheMaxNum = value;
}
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
public void SetIsShowMsg(bool value)
{
Helper.IsShowMsg = value;
}
/// <summary>
///
/// :1-CacheMaxNum, 10%-20%
/// </summary>
/// <param name="value"></param>
public void SetBlockNumExt(int value)
{
if (value > 0 && value <= _CacheMaxNum)
{
_BlockNumExt = value;
}
}
/// <summary>
///
/// :1-max,
/// , ,
/// </summary>
/// <param name="value"></param>
public void SetBlockSpanTime(int value)
{
if (value > 0)
{
_BlockSpanTime = value;
}
}
#endregion
#region
/// <summary>
///
/// </summary>
private Thread _runner = null;
/// <summary>
///
/// </summary>
private ConcurrentLinkedQueue<string> _Myqueue = null;
/// <summary>
///
/// </summary>
private Hashtable _DataKey = null;
/// <summary>
///
/// </summary>
private Queue _DataQueue = null;
/// <summary>
/// : 1
/// </summary>
private int _TimeSpan = 3000;
/// <summary>
///
/// </summary>
private Thread _Timer = null;
/// <summary>
/// Cache
/// </summary>
private int _CacheMaxNum = 500000;
/// <summary>
///
/// </summary>
private int _BlockNumExt = 10000;
/// <summary>
///
/// </summary>
private int _BlockSpanTime = 100;
#endregion
#region
private void StartRun()
{
_runner = new Thread(DoAction);
_runner.Start();
Helper.ShowMsg(" !");
}
private string GetItem()
{
string tp = string.Empty;
bool result = _Myqueue.TryDequeue(out tp);
return tp;
}
/// <summary>
///
/// </summary>
private void DoAction()
{
while (true)
{
while (!_Myqueue.IsEmpty)
{
string item = GetItem();
_DataQueue.Enqueue(item);
if (!_DataKey.ContainsKey(item))
{
_DataKey.Add(item, DateTime.Now);
}
}
//Helper.ShowMsg(" , ...");
Thread.Sleep(2);
}
}
/// <summary>
///
/// </summary>
private void DoTicket()
{
while (true)
{
Helper.ShowMsg(" :" + _DataQueue.Count.ToString());
if (_DataQueue.Count > _CacheMaxNum)
{
while (true)
{
Helper.ShowMsg(string.Format(" :{0}, :{1}, ...", _DataQueue.Count, _CacheMaxNum.ToString()));
string item = _DataQueue.Dequeue().ToString();
if (!string.IsNullOrEmpty(item))
{
if (_DataKey.ContainsKey(item))
{
_DataKey.Remove(item);
}
if (_DataQueue.Count <= _CacheMaxNum)
{
Helper.ShowMsg(" , ...");
break;
}
}
}
}
Thread.Sleep(_TimeSpan);
}
}
/// <summary>
///
///
///
/// </summary>
private void BlockThread()
{
if (_DataQueue.Count > _CacheMaxNum + _BlockNumExt)
{
Thread.Sleep(_BlockSpanTime);
}
}
#endregion
#region
/// <summary>
///
/// </summary>
public void Start()
{
if (_runner == null)
{
StartRun();
}
else
{
if (_runner.IsAlive == false)
{
StartRun();
}
}
}
/// <summary>
///
/// </summary>
public void Stop()
{
if (_runner != null)
{
_runner.Abort();
_runner = null;
}
}
/// <summary>
///
/// </summary>
/// <param name="item"> </param>
/// <returns>true: , ,false: , </returns>
public bool AddItem(string item)
{
BlockThread();
item = Helper.MakeMd5(item);
if (_DataKey.ContainsKey(item))
{
return false;
}
else
{
_Myqueue.Enqueue(item);
return true;
}
}
/// <summary>
///
/// </summary>
/// <param name="item"> </param>
/// <returns>true: ,false: </returns>
public bool CheckItem(string item)
{
item = Helper.MakeMd5(item);
return _DataKey.ContainsKey(item);
}
#endregion
}
}
아 날로 그 테스트 코드:
private static string _example = Guid.NewGuid().ToString();
private static UniqueCheck _uck = null;
static void Main(string[] args)
{
_uck = UniqueCheck.GetInstance();
_uck.Start();
_uck.SetIsShowMsg(false);
_uck.SetCacheMaxNum(20000000);
_uck.SetBlockNumExt(1000000);
_uck.SetTimeSpan(6000);
_uck.AddItem(_example);
Thread[] threads = new Thread[20];
for (int i = 0; i < 20; i++)
{
threads[i] = new Thread(AddInfo);
threads[i].Start();
}
Thread checkthread = new Thread(CheckInfo);
checkthread.Start();
string value = Console.ReadLine();
checkthread.Abort();
for (int i = 0; i < 50; i++)
{
threads[i].Abort();
}
_uck.Stop();
}
static void AddInfo()
{
while (true)
{
_uck.AddItem(Guid.NewGuid().ToString());
}
}
static void CheckInfo()
{
while (true)
{
Console.WriteLine(" :{0}...", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff"));
Console.WriteLine(" :{0}", _uck.AddItem(_example));
Console.WriteLine(" :{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff"));
// ,
//Thread.Sleep(1000);
}
}
테스트 캡 처:총결산
이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.