文档章节

C#创建安全的栈(Stack)存储结构

彭泽0902
 彭泽0902
发布于 2016/11/24 18:47
字数 4012
阅读 0
收藏 0
点赞 0
评论 0

    在C#中,用于存储的结构较多,如:DataTable,DataSet,List,Dictionary,Stack等结构,各种结构采用的存储的方式存在差异,效率也必然各有优缺点。现在介绍一种后进先出的数据结构。

   谈到存储结构,我们在项目中使用的较多。对于Task存储结构,栈与队列是类似的结构,在使用的时候采用不同的方法。C#中栈(Stack)是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义;堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小。

    在C#中,栈通常保存着我们代码执行的步骤。C#中的引用类型存储在栈中,在程序运行的时候,每个线程(Thread)都会维护一个自己的专属线程堆栈。当一个方法被调用的时候,主线程开始在所属程序集的元数据中,查找被调用方法,然后通过JIT即时编译并把结果(一般是本地CPU指令)放在栈顶。CPU通过总线从栈顶取指令,驱动程序以执行下去。

    以上对栈这个数据结构进行了一个简单的介绍,现在看一下C#实现栈结构的底层方法:

/// <summary>
    /// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 类的新实例,该实例为空并且具有默认初始容量。
    /// </summary>
    [__DynamicallyInvokable]
    public Stack();
    /// <summary>
    /// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 类的新实例,该实例为空,具有指定的初始容量或默认的初始容量(其中较大的一个)。
    /// </summary>
    /// <param name="capacity"><see cref="T:System.Collections.Generic.Stack`1"/> 可包含的初始元素数。</param><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
    [__DynamicallyInvokable]
    public Stack(int capacity);
    /// <summary>
    /// 初始化 <see cref="T:System.Collections.Generic.Stack`1"/> 类的新实例,该实例包含从指定集合复制的元素并且具有足够的容量来容纳所复制的元素。
    /// </summary>
    /// <param name="collection">从中复制元素的集合。</param><exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is null.</exception>
    [__DynamicallyInvokable]
    public Stack(IEnumerable<T> collection);

   以上是对stack的部分方法的介绍,由于在操作数据存储的同时,会考虑到线程的安全性。

   进程作为操作系统执行程序的基本单位,拥有应用程序的资源,进程包含线程,进程的资源被线程共享,线程不拥有资源。线程分为前台线程和后台线程,通过Thread类新建线程默认为前台线程。当所有前台线程关闭时,所有的后台线程也会被直接终止,不会抛出异常。

    接下来看一下ReaderWriterLockSlim类:

/// <summary>
  /// 表示用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。
  /// </summary>
  [__DynamicallyInvokable]
  [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true, Synchronization = true)]
  [HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort = true)]
  public class ReaderWriterLockSlim : IDisposable
  {
    /// <summary>
    /// 使用默认属性值初始化 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 类的新实例。
    /// </summary>
    [__DynamicallyInvokable]
    public ReaderWriterLockSlim();
    /// <summary>
    /// 在指定锁定递归策略的情况下初始化 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 类的新实例。
    /// </summary>
    /// <param name="recursionPolicy">枚举值之一,用于指定锁定递归策略。</param>
    [__DynamicallyInvokable]
    public ReaderWriterLockSlim(LockRecursionPolicy recursionPolicy);
    /// <summary>
    /// 尝试进入读取模式锁定状态。
    /// </summary>
    /// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入读取的模式。- 或 -当它已经包含写入锁时,当前线程可能不会获取读的锁定。- 或 -递归数将超出该计数器的容量。此限制是很大的应用程序应永远不会遇到它。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public void EnterReadLock();
    /// <summary>
    /// 尝试进入读取模式锁定状态,可以选择超时时间。
    /// </summary>
    /// 
    /// <returns>
    /// 如果调用线程已进入读取模式,则为 true;否则为 false。
    /// </returns>
    /// <param name="timeout">等待的间隔;或为 -1 毫秒,表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> 为负数,但它不等于-1 毫秒为单位),这是唯一允许的值为负。- 或 -值 <paramref name="timeout"/> 大于 <see cref="F:System.Int32.MaxValue"/> 毫秒为单位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterReadLock(TimeSpan timeout);
    /// <summary>
    /// 尝试进入读取模式锁定状态,可以选择整数超时时间。
    /// </summary>
    /// 
    /// <returns>
    /// 如果调用线程已进入读取模式,则为 true;否则为 false。
    /// </returns>
    /// <param name="millisecondsTimeout">等待的毫秒数,或为 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> 为负数,但它不是等于 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),这是唯一允许的值为负。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterReadLock(int millisecondsTimeout);
    /// <summary>
    /// 尝试进入写入模式锁定状态。
    /// </summary>
    /// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已在任何模式下进入该锁。- 或 -当前线程已进入读取的模式,因此尝试进入锁定状态写模式,则会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public void EnterWriteLock();
    /// <summary>
    /// 尝试进入写入模式锁定状态,可以选择超时时间。
    /// </summary>
    /// 
    /// <returns>
    /// 如果调用线程已进入写入模式,则为 true;否则为 false。
    /// </returns>
    /// <param name="timeout">等待的间隔;或为 -1 毫秒,表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入写入模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> 为负数,但它不等于-1 毫秒为单位),这是唯一允许的值为负。- 或 -值 <paramref name="timeout"/> 大于 <see cref="F:System.Int32.MaxValue"/> 毫秒为单位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterWriteLock(TimeSpan timeout);
    /// <summary>
    /// 尝试进入写入模式锁定状态,可以选择超时时间。
    /// </summary>
    /// 
    /// <returns>
    /// 如果调用线程已进入写入模式,则为 true;否则为 false。
    /// </returns>
    /// <param name="millisecondsTimeout">等待的毫秒数,或为 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入写入模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> 为负数,但它不是等于 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),这是唯一允许的值为负。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterWriteLock(int millisecondsTimeout);
    /// <summary>
    /// 尝试进入可升级模式锁定状态。
    /// </summary>
    /// <exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已在任何模式下进入该锁。- 或 -当前线程已进入读取的模式,因此尝试进入可升级模式将有死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public void EnterUpgradeableReadLock();
    /// <summary>
    /// 尝试进入可升级模式锁定状态,可以选择超时时间。
    /// </summary>
    /// 
    /// <returns>
    /// 如果调用线程已进入可升级模式,则为 true;否则为 false。
    /// </returns>
    /// <param name="timeout">等待的间隔;或为 -1 毫秒,表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入可升级模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> 为负数,但它不等于-1 毫秒为单位),这是唯一允许的值为负。- 或 -值 <paramref name="timeout"/> 大于 <see cref="F:System.Int32.MaxValue"/> 毫秒为单位)。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterUpgradeableReadLock(TimeSpan timeout);
    /// <summary>
    /// 尝试进入可升级模式锁定状态,可以选择超时时间。
    /// </summary>
    /// 
    /// <returns>
    /// 如果调用线程已进入可升级模式,则为 true;否则为 false。
    /// </returns>
    /// <param name="millisecondsTimeout">等待的毫秒数,或为 -1 (<see cref="F:System.Threading.Timeout.Infinite"/>),表示无限期等待。</param><exception cref="T:System.Threading.LockRecursionException"><see cref="P:System.Threading.ReaderWriterLockSlim.RecursionPolicy"/> 属性是 <see cref="F:System.Threading.LockRecursionPolicy.NoRecursion"/> 和当前的线程已进入该锁。- 或 -当前线程最初在读取模式中,输入该锁,因此尝试进入可升级模式会创建导致死锁的可能性。- 或 -递归数将超出该计数器的容量。限制为应用程序应永远不会遇到它太大。</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> 为负数,但它不是等于 <see cref="F:System.Threading.Timeout.Infinite"/> (-1),这是唯一允许的值为负。</exception><exception cref="T:System.ObjectDisposedException"><see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象已被释放。</exception>
    [__DynamicallyInvokable]
    public bool TryEnterUpgradeableReadLock(int millisecondsTimeout);
    /// <summary>
    /// 减少读取模式的递归计数,并在生成的计数为 0(零)时退出读取模式。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException">在读取模式中,当前线程不已进入该锁。</exception>
    [__DynamicallyInvokable]
    public void ExitReadLock();
    /// <summary>
    /// 减少写入模式的递归计数,并在生成的计数为 0(零)时退出写入模式。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException">当前线程不已进入写入模式的锁定。</exception>
    [__DynamicallyInvokable]
    public void ExitWriteLock();
    /// <summary>
    /// 减少可升级模式的递归计数,并在生成的计数为 0(零)时退出可升级模式。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException">当前线程不已进入可升级模式的锁定。</exception>
    [__DynamicallyInvokable]
    public void ExitUpgradeableReadLock();
    /// <summary>
    /// 释放 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 类的当前实例所使用的所有资源。
    /// </summary>
    /// <exception cref="T:System.Threading.SynchronizationLockException"><see cref="P:System.Threading.ReaderWriterLockSlim.WaitingReadCount"/> 是大于零。- 或 -<see cref="P:System.Threading.ReaderWriterLockSlim.WaitingUpgradeCount"/> 是大于零。- 或 -<see cref="P:System.Threading.ReaderWriterLockSlim.WaitingWriteCount"/> 是大于零。</exception><filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public void Dispose();
    /// <summary>
    /// 获取一个值,该值指示当前线程是否已进入读取模式的锁定状态。
    /// </summary>
    /// 
    /// <returns>
    /// 如果当前线程已进入读取模式,则为 true;否则为 false。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public bool IsReadLockHeld { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取一个值,该值指示当前线程是否已进入可升级模式的锁定状态。
    /// </summary>
    /// 
    /// <returns>
    /// 如果当前线程已进入可升级模式,则为 true;否则为 false。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public bool IsUpgradeableReadLockHeld { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取一个值,该值指示当前线程是否已进入写入模式的锁定状态。
    /// </summary>
    /// 
    /// <returns>
    /// 如果当前线程已进入写入模式,则为 true;否则为 false。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public bool IsWriteLockHeld { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取一个值,该值指示当前 <see cref="T:System.Threading.ReaderWriterLockSlim"/> 对象的递归策略。
    /// </summary>
    /// 
    /// <returns>
    /// 枚举值之一,用于指定锁定递归策略。
    /// </returns>
    [__DynamicallyInvokable]
    public LockRecursionPolicy RecursionPolicy { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取已进入读取模式锁定状态的独有线程的总数。
    /// </summary>
    /// 
    /// <returns>
    /// 已进入读取模式锁定状态的独有线程的数量。
    /// </returns>
    [__DynamicallyInvokable]
    public int CurrentReadCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取当前线程进入读取模式锁定状态的次数,用于指示递归。
    /// </summary>
    /// 
    /// <returns>
    /// 如果当前线程未进入读取模式,则为 0(零);如果线程已进入读取模式但却不是以递归方式进入的,则为 1;或者如果线程已经以递归方式进入锁定模式 n - 1 次,则为 n。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int RecursiveReadCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取当前线程进入可升级模式锁定状态的次数,用于指示递归。
    /// </summary>
    /// 
    /// <returns>
    /// 如果当前线程没有进入可升级模式,则为 0;如果线程已进入可升级模式却不是以递归方式进入的,则为 1;或者如果线程已经以递归方式进入可升级模式 n - 1 次,则为 n。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int RecursiveUpgradeCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取当前线程进入写入模式锁定状态的次数,用于指示递归。
    /// </summary>
    /// 
    /// <returns>
    /// 如果当前线程没有进入写入模式,则为 0;如果线程已进入写入模式却不是以递归方式进入的,则为 1;或者如果线程已经以递归方式进入写入模式 n - 1 次,则为 n。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int RecursiveWriteCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取等待进入读取模式锁定状态的线程总数。
    /// </summary>
    /// 
    /// <returns>
    /// 等待进入读取模式的线程总数。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int WaitingReadCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取等待进入可升级模式锁定状态的线程总数。
    /// </summary>
    /// 
    /// <returns>
    /// 等待进入可升级模式的线程总数。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int WaitingUpgradeCount { [__DynamicallyInvokable] get; }
    /// <summary>
    /// 获取等待进入写入模式锁定状态的线程总数。
    /// </summary>
    /// 
    /// <returns>
    /// 等待进入写入模式的线程总数。
    /// </returns>
    /// <filterpriority>2</filterpriority>
    [__DynamicallyInvokable]
    public int WaitingWriteCount { [__DynamicallyInvokable] get; }
  }

     以上是对Stack和线程的相关知识的浅述,现在介绍一下线程安全的Stack:

 

/// <summary>
    /// 表示对象的后进先出线程安全集合(栈结构)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class TStack<T> : IEnumerable<T>, ICollection
    {
        /// <summary>
        /// 内部堆栈
        /// </summary>
        private readonly Stack<T> _mStack;

        /// <summary>
        /// 锁访问堆栈(用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。)
        /// </summary>
        private readonly ReaderWriterLockSlim _lockStack = new ReaderWriterLockSlim();

        /// <summary>
        /// 仅用于SyncRoot属性
        /// </summary>
        private readonly object _objSyncRoot = new object();

        // Variables
        /// <summary>
        /// 初始化一个新的实例 <see cref="TStack{T}"/> class.
        /// </summary>
        public TStack()
        {
            _mStack = new Stack<T>();
        }

        /// <summary>
        /// 初始化一个新的实例 <see cref="TStack{T}"/> class.
        /// </summary>
        /// <param name="col">
        /// 开始集合
        /// </param>
        public TStack(IEnumerable<T> col)
        {
            _mStack = new Stack<T>(col);
        }

        // Init
        /// <summary>
        /// 获取枚举器
        /// </summary>
        public IEnumerator<T> GetEnumerator()
        {
            Stack<T> localStack = null;

            // 初始化枚举器
            _lockStack.PerformUsingReadLock(() =>
            {
                // 创建一个m_tlist副本
                localStack = new Stack<T>(_mStack);
            });

            // 获取枚举器
            foreach (T item in localStack)
                yield return item;
        }


        /// <summary>
        /// 获取枚举器
        /// </summary>
        IEnumerator IEnumerable.GetEnumerator()
        {
            Stack<T> localStack = null;

            // 初始化枚举器
            _lockStack.PerformUsingReadLock(() =>
            {
                // 创建一个m_TList的副本
                localStack = new Stack<T>(_mStack);
            });

            // 获取枚举器
            foreach (T item in localStack)
                yield return item;
        }


        /// <summary>
        /// 复制到一个数组
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        public void CopyTo(Array array, int index)
        {
            _lockStack.PerformUsingReadLock(() => _mStack.ToArray().CopyTo(array, index));
        }

        /// <summary>
        ///堆栈中的项目数
        /// </summary>
        public int Count
        {
            get
            {
                return _lockStack.PerformUsingReadLock(() => _mStack.Count);
            }
        }

        /// <summary>
        /// 总为真
        /// </summary>
        public bool IsSynchronized
        {
            get { return true; }
        }

        /// <summary>
        ///同步根
        /// </summary>
        public object SyncRoot
        {
            get { return _objSyncRoot; }
        }


        /// <summary>
        ///清除集合
        /// </summary>
        public void Clear()
        {
            _lockStack.PerformUsingWriteLock(() => _mStack.Clear());
        }

        // Clear
        /// <summary>
        ///如果项目在堆栈中,则为true
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(T item)
        {
            return _lockStack.PerformUsingReadLock(() => _mStack.Contains(item));
        }

        // 包含
        /// <summary>
        /// 返回堆栈中的顶部项,而不从堆栈中删除它
        /// </summary>
        /// <returns></returns>
        public T Peek()
        {
            return _lockStack.PerformUsingReadLock(() => _mStack.Peek());
        }

        // Peek
        /// <summary>
        ///删除并返回堆栈中的顶部项目
        /// </summary>
        /// <returns></returns>
        public T Pop()
        {
            return _lockStack.PerformUsingWriteLock(() => _mStack.Pop());
        }

        // Pop
        /// <summary>
        /// 将一个项目插入堆栈
        /// </summary>
        /// <param name="item"></param>
        public void Push(T item)
        {
            _lockStack.PerformUsingWriteLock(() => _mStack.Push(item));
        }

        // Push
        /// <summary>
        ///将堆栈转换为数组
        /// </summary>
        /// <returns></returns>
        public T[] ToArray()
        {
            return _lockStack.PerformUsingReadLock(() => _mStack.ToArray());
        }

        // ToArray
        /// <summary>
        /// 将容量设置为堆栈中实际的元素数量
        /// </summary>
        public void TrimExcess()
        {
            _lockStack.PerformUsingWriteLock(() => _mStack.TrimExcess());
        }
    }

    以上的操作方法继承了IEnumerable<T>, ICollection两个接口。有兴趣的,可以对IEnumerable<T>, ICollection两个接口进行细致的了解。

 

© 著作权归作者所有

共有 人打赏支持
彭泽0902
粉丝 0
博文 44
码字总数 57771
作品 0
武汉
高级程序员
转载:C#中的泛型

原文地址:http://birdshover.cnblogs.com/articles/392127.html 泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性。泛型为.NET框架引入了类型参数(type parameters)的概念。...

随智阔 ⋅ 2014/03/21 ⋅ 0

C# 队列和栈 线程安全

队列是其元素以先进先出(FIFO)的方式来处理集合,先入队的元素会先读取。 栈是和队列非常类似的另一个容器,栈和队列最大的区别是后进先出(LIFO),也可以说成先进后出。 队列在现实生活中的例...

天才小龙 ⋅ 01/05 ⋅ 0

JVM中的Stack和Frame

JVM执行Java程序时需要装载各种数据,比如类型信息(Class)、类型实例(Instance)、常量数据(Constant)、本地变量等。不同的数据存放在不同的内存区中,这些数据内存区称作“运行时数据区...

tantexian ⋅ 2016/08/25 ⋅ 0

linux源码分析(三)-start_kernel

前置:这里使用的linux版本是4.8,x86体系。 start_kernel是过了引导阶段,进入到了内核启动阶段的入口。函数在init/main.c中。 settaskstackendmagic(&init_task); 这个函数是设置操作系统的...

王二狗子11 ⋅ 01/07 ⋅ 0

c#泛型的使用

在2005年底微软公司正式发布了C# 2.0,与C# 1.x相比,新版本增加了很多新特性,其中最重要的是对泛型的支持。通过泛型,我们可以定义类型安全的数据结构,而无需使用实际的数据类型。这能显著...

zsj2018 ⋅ 2008/08/21 ⋅ 0

Java虚拟机运行时数据区结构

本文部分参考自《Java虚拟机规范(Java SE 7版)》的中译本和周志明的《深入理解Java虚拟机》,另加个人理解。原书对Java虚拟机运行时数据区描述只有6页,同时参考其他网络网资料,个人能力所...

foodon ⋅ 2014/12/09 ⋅ 4

Java实现栈Stack_栈内部使用数组存储结构

Java实现栈Stack_栈内部使用数组存储结构 抽象数据类型栈的定义: 栈(stack),是限定在表尾进行插入或删除操作的线性表,因此对栈来说表尾有其特殊的含义,称为栈顶,相应的,表头端称为栈...

秋风醉了 ⋅ 2014/09/14 ⋅ 0

[收藏]网上搜集的一系列C#面试题(持续更新……)

1.请你说说.NET中类和结构的区别? 答:结构和类具有大体的语法,但是结构受到的限制比类要多。结构不能申明有默认的构造函 数,为结构的副本是又编译器创建和销毁的,所以不需要默 认的构造函...

zting科技 ⋅ 2017/01/11 ⋅ 0

java数据结构与算法之栈(Stack)设计与实现

一、栈的抽象数据类型  栈是一种用于存储数据的简单数据结构,有点类似链表或者顺序表(统称线性表),栈与线性表的最大区别是数据的存取的操作,我们可以这样认为栈(Stack)是一种特殊的线性...

千涯秋瑟 ⋅ 01/02 ⋅ 0

C# 之泛型详解

什么是泛型 我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数...

青夜之衫 ⋅ 2017/12/05 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

线程池

一、线程池:提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了响应的速度。 二、线程池的体系结构: java.util.concurrent.Executor : 负责线程的使用...

stars永恒 ⋅ 19分钟前 ⋅ 0

你值5K还是15K?实战案例,测测你的分析功力

本文源自陈老师遇到的真实案例。 老板说:“我们今年准备参加展会,做一年。以前我没参加过,没关系,这里有一份展会数据,你回去分析下哪些有价值,后边组织的时候有个指导”。现在你收到任...

加米谷大数据 ⋅ 20分钟前 ⋅ 0

中文转英文功能

package com.sysware.task.util;import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;import net.sourceforge.pinyin4j.for......

AK灬 ⋅ 21分钟前 ⋅ 0

JNI Java层类关联C/C++层的类

Android开发时,因为要实现某某功能,需要集成算法公司的算法库(so库),这就需要自己编写JNI。 通常这些库提供的接口可以概况成1、初始化 2、算法处理 3、释放 4、打印版本号 初始化后会返...

国仔饼 ⋅ 25分钟前 ⋅ 0

maven下载jar包改为阿里云的maven库

一:修改maven安装路径中conf文件夹下的setting.xml文件 <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/......

夜醒者 ⋅ 25分钟前 ⋅ 0

电商用户行为分析大数据平台相关系列10-基础数据结构分析

电商用户行为分析大数据平台相关系列1-环境介绍 电商用户行为分析大数据平台相关系列2-HADOOP环境搭建 电商用户行为分析大数据平台相关系列3-HIVE安装 电商用户行为分析大数据平台相关系列4...

xiaomin0322 ⋅ 26分钟前 ⋅ 0

使用readLine()方法遇到的坑

下午玩 TCP/IP 的 Socket 通信时,使用 BufferedReader 的 readLine() 遇到了一个坑,现在终于解决了,特此记录下来。 程序很简单,客户段从控制台读取用户输入,然后发送至服务器端,主要代...

孟飞阳 ⋅ 26分钟前 ⋅ 0

基于Hadoop集群的Hive安装配置(Derby数据库)

Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据,提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行(具体的Hive架构大家自行搜索)。接下来主要讲下Hadoop集群下...

海岸线的曙光 ⋅ 27分钟前 ⋅ 0

CoreOS裸机iso安装和相关配置

裸机通过iso安装CoreOS,个人趟了很多坑,以下就是完整的从零开始部署和配置的过程,希望对大家有用。 一、安装CoreOS到硬盘 1. 准备Live iso镜像,制作好usb启动盘 Live iso下载地址 2. 搭建...

ykbj ⋅ 32分钟前 ⋅ 0

jquery控制表格锁列(转)

表格已经完成后新加的需求,要实现锁表格的第一列。很多带这种效果的都是js封装的框架或者具体某种框架的组件,不适用解决当前问题。作为后端开发又实在不熟样式,搜到了一个可以用的,虽然样...

刘昌鑫 ⋅ 34分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部