IdWorker 2

using System;

namespace SnowflakeTest
{
    /**
    * tweeter的snowflake 移植到Java翻译成Net:
    *   (a) id构成: 42位的时间前缀 + 10位的节点标识 + 12位的sequence避免并发的数字(12位不够用时强制得到新的时间前缀)
    *       注意这里进行了小改动: snowkflake是5位的datacenter加5位的机器id; 这里变成使用10位的机器id
    *   (b) 对系统时间的依赖性非常强,需关闭ntp的时间同步功能。当检测到ntp时间调整后,将会拒绝分配id
    */
    public class IdWorker
    {
        private static object _lockkey = new object();
        private static DateTime dt = new DateTime();

        private long _twepoch = 1451606400000L; /*2016-01-01*/// 时间起始标记点,作为基准,一般取系统的最近时间()

        private const int _workerIdBits = 5;
        private const int _datacenterIdBits = 5; // 机器标识位数
        private const int _sequenceBits = 12;

        private long _workerId;
        private long _datacenterId;
        private long _sequence;// 0,并发控制

        private long _maxWorkerId = -1L ^ (-1L << _workerIdBits);// 机器ID最大值: 1023
        private long _maxDatacenterId = -1L ^ (-1L << _datacenterIdBits);
        private long _sequenceMask = -1L ^ (-1L << _sequenceBits);

        private int _workerIdShift = _sequenceBits;
        private int _datacenterIdShift = _sequenceBits + _workerIdBits;
        private int _timestampLeftShift = _sequenceBits + _workerIdBits + _datacenterIdBits;

        private long _lastTimestamp = -1L;

        public IdWorker(long workerId, long datacenterId)
        {
            if (workerId > _maxWorkerId || workerId < 0)
            {
                throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", _maxWorkerId));
            }
            if (datacenterId > _maxDatacenterId || datacenterId < 0)
            {
                throw new Exception(string.Format("datacenter Id can't be greater than {0} or less than 0", _maxWorkerId));
            }
            _workerId = workerId;
            _datacenterId = datacenterId;
        }

        public long NextId()
        {
            lock (_lockkey)
            {
                long timestamp = TimeGen();
                if (timestamp < _lastTimestamp)
                {
                    throw new Exception(string.Format("Clock moved backwards.  Refusing to generate id for {0} milliseconds",
                        _lastTimestamp - timestamp));
                }

                if (_lastTimestamp == timestamp)
                {
                    _sequence = (_sequence + 1) & _sequenceMask;
                    if (_sequence == 0)
                    {
                        timestamp = TilNextMillis(_lastTimestamp);
                    }
                }
                else
                {
                    _sequence = 0L;
                }

                _lastTimestamp = timestamp;

                return ((timestamp - _twepoch) << _timestampLeftShift) | (_datacenterId << _datacenterIdShift) |
                       (_workerId << _workerIdShift) | _sequence;
            }
        }
        /**
         * 获得系统当前毫秒数
         */
        protected long TimeGen()
        {
            return dt.CurrentTimeMillis();
        }
        /**
        * 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
        */
        protected long TilNextMillis(long lastTimestamp)
        {
            long timestamp = TimeGen();
            while (timestamp <= lastTimestamp)
            {
                timestamp = TimeGen();
            }
            return timestamp;
        }
    }

    public static class DateTimeExtensions
    {
        private static readonly DateTime Jan1St1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        /// <summary>
        /// java currentTimeMillis
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static long CurrentTimeMillis(this DateTime dt)
        {
            return (long) ((DateTime.UtcNow - Jan1St1970).TotalMilliseconds);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SnowflakeTest
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            //Console.WriteLine(GetTime("1478856034933"));
            //return;
            var t = ((1478856034933 - 1451606400000) << 22) | (1 << 17) | (1 << 12) | 0;
            var tt = ((t >> 22) | (1 >> 17) | (1 >> 12) | 0)+ 1451606400000;
            Console.WriteLine(t+"=="+ tt);//1478856034933  114293252798156800
            return;
            IdWorker idWorker = new IdWorker(1, 1);
            int len = 200;
            long[] ids = new long[len];

            for (int i = 0; i < len; i++)
            {
                ids[i] = idWorker.NextId();
                //Thread.Sleep(1);
            }
            foreach (long id in ids)
            {
                Console.WriteLine("{0}", Convert.ToString(id));
            }
            
            //Console.WriteLine("sss:"+ new IdWorker(1, 1).TimeGen());114280345465131008
        }

        /// <summary>
        /// DateTime时间格式转换为Unix时间戳格式
        /// </summary>
        /// <param name="time"> DateTime时间格式</param>
        /// <returns>Unix时间戳格式</returns>
        public static int ConvertDateTimeInt(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (int)(time - startTime).TotalSeconds;
        }

        /// <summary>
        /// 时间戳转为C#格式时间
        /// </summary>
        /// <param name="timeStamp">Unix时间戳格式</param>
        /// <returns>C#格式时间</returns>
        public static DateTime GetTime(string timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp + "0000");
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值