@@ -0,0 +1,258 @@ | |||
## Ignore Visual Studio temporary files, build results, and | |||
## files generated by popular Visual Studio add-ons. | |||
# User-specific files | |||
*.suo | |||
*.user | |||
*.userosscache | |||
*.sln.docstates | |||
*.editorconfig | |||
# User-specific files (MonoDevelop/Xamarin Studio) | |||
*.userprefs | |||
# Build results | |||
[Dd]ebug/ | |||
[Dd]ebugPublic/ | |||
[Rr]elease/ | |||
[Rr]eleases/ | |||
x64/ | |||
x86/ | |||
bld/ | |||
[Bb]in/ | |||
[Oo]bj/ | |||
[Ll]og/ | |||
# Visual Studio 2015 cache/options directory | |||
**/.vs/ | |||
# Uncomment if you have tasks that create the project's static files in wwwroot | |||
#wwwroot/ | |||
# MSTest test Results | |||
[Tt]est[Rr]esult*/ | |||
[Bb]uild[Ll]og.* | |||
# NUNIT | |||
*.VisualState.xml | |||
TestResult.xml | |||
# Build Results of an ATL Project | |||
[Dd]ebugPS/ | |||
[Rr]eleasePS/ | |||
dlldata.c | |||
# DNX | |||
project.lock.json | |||
artifacts/ | |||
*_i.c | |||
*_p.c | |||
*_i.h | |||
*.ilk | |||
*.meta | |||
*.obj | |||
*.pch | |||
*.pdb | |||
*.pgc | |||
*.pgd | |||
*.rsp | |||
*.sbr | |||
*.tlb | |||
*.tli | |||
*.tlh | |||
*.tmp | |||
*.tmp_proj | |||
*.log | |||
*.vspscc | |||
*.vssscc | |||
.builds | |||
*.pidb | |||
*.svclog | |||
*.scc | |||
# Chutzpah Test files | |||
_Chutzpah* | |||
# Visual C++ cache files | |||
ipch/ | |||
*.aps | |||
*.ncb | |||
*.opendb | |||
*.opensdf | |||
*.sdf | |||
*.cachefile | |||
*.VC.db | |||
*.VC.VC.opendb | |||
# Visual Studio profiler | |||
*.psess | |||
*.vsp | |||
*.vspx | |||
*.sap | |||
# TFS 2012 Local Workspace | |||
$tf/ | |||
# Guidance Automation Toolkit | |||
*.gpState | |||
# ReSharper is a .NET coding add-in | |||
_ReSharper*/ | |||
*.[Rr]e[Ss]harper | |||
*.DotSettings.user | |||
# JustCode is a .NET coding add-in | |||
.JustCode | |||
# TeamCity is a build add-in | |||
_TeamCity* | |||
# DotCover is a Code Coverage Tool | |||
*.dotCover | |||
# NCrunch | |||
_NCrunch_* | |||
.*crunch*.local.xml | |||
nCrunchTemp_* | |||
# MightyMoose | |||
*.mm.* | |||
AutoTest.Net/ | |||
# Web workbench (sass) | |||
.sass-cache/ | |||
# Installshield output folder | |||
[Ee]xpress/ | |||
# DocProject is a documentation generator add-in | |||
DocProject/buildhelp/ | |||
DocProject/Help/*.HxT | |||
DocProject/Help/*.HxC | |||
DocProject/Help/*.hhc | |||
DocProject/Help/*.hhk | |||
DocProject/Help/*.hhp | |||
DocProject/Help/Html2 | |||
DocProject/Help/html | |||
# Click-Once directory | |||
publish/ | |||
# Publish Web Output | |||
*.[Pp]ublish.xml | |||
*.azurePubxml | |||
# TODO: Comment the next line if you want to checkin your web deploy settings | |||
# but database connection strings (with potential passwords) will be unencrypted | |||
*.pubxml | |||
*.publishproj | |||
# Microsoft Azure Web App publish settings. Comment the next line if you want to | |||
# checkin your Azure Web App publish settings, but sensitive information contained | |||
# in these scripts will be unencrypted | |||
PublishScripts/ | |||
# NuGet Packages | |||
*.nupkg | |||
*.snupkg | |||
# The packages folder can be ignored because of Package Restore | |||
**/packages/* | |||
# except build/, which is used as an MSBuild target. | |||
!**/packages/build/ | |||
# Uncomment if necessary however generally it will be regenerated when needed | |||
#!**/packages/repositories.config | |||
# NuGet v3's project.json files produces more ignoreable files | |||
*.nuget.props | |||
*.nuget.targets | |||
# Microsoft Azure Build Output | |||
csx/ | |||
*.build.csdef | |||
# Microsoft Azure Emulator | |||
ecf/ | |||
rcf/ | |||
# Windows Store app package directories and files | |||
AppPackages/ | |||
BundleArtifacts/ | |||
Package.StoreAssociation.xml | |||
_pkginfo.txt | |||
# Visual Studio cache files | |||
# files ending in .cache can be ignored | |||
*.[Cc]ache | |||
# but keep track of directories ending in .cache | |||
!*.[Cc]ache/ | |||
# Others | |||
ClientBin/ | |||
~$* | |||
*~ | |||
*.dbmdl | |||
*.dbproj.schemaview | |||
*.pfx | |||
*.publishsettings | |||
node_modules/ | |||
orleans.codegen.cs | |||
# Since there are multiple workflows, uncomment next line to ignore bower_components | |||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | |||
#bower_components/ | |||
# RIA/Silverlight projects | |||
Generated_Code/ | |||
# Backup & report files from converting an old project file | |||
# to a newer Visual Studio version. Backup files are not needed, | |||
# because we have git ;-) | |||
_UpgradeReport_Files/ | |||
Backup*/ | |||
UpgradeLog*.XML | |||
UpgradeLog*.htm | |||
# SQL Server files | |||
*.mdf | |||
*.ldf | |||
# Business Intelligence projects | |||
*.rdl.data | |||
*.bim.layout | |||
*.bim_*.settings | |||
# Microsoft Fakes | |||
FakesAssemblies/ | |||
# GhostDoc plugin setting file | |||
*.GhostDoc.xml | |||
# Node.js Tools for Visual Studio | |||
.ntvs_analysis.dat | |||
# Visual Studio 6 build log | |||
*.plg | |||
# Visual Studio 6 workspace options file | |||
*.opt | |||
# Visual Studio LightSwitch build output | |||
**/*.HTMLClient/GeneratedArtifacts | |||
**/*.DesktopClient/GeneratedArtifacts | |||
**/*.DesktopClient/ModelManifest.xml | |||
**/*.Server/GeneratedArtifacts | |||
**/*.Server/ModelManifest.xml | |||
_Pvt_Extensions | |||
# Paket dependency manager | |||
.paket/paket.exe | |||
paket-files/ | |||
# FAKE - F# Make | |||
.fake/ | |||
# JetBrains Rider | |||
.idea/ | |||
*.sln.iml | |||
# macOS | |||
.DS_Store |
@@ -13,28 +13,28 @@ namespace Yitter.OrgSystem.TestA | |||
private IIdGenerator IdGen; | |||
private Hashtable ids = new Hashtable(); | |||
public IList<long> idList = new List<long>(); | |||
private int GenNumber; | |||
private int GenIdCount; | |||
private int WorkerId; | |||
public GenTest(IIdGenerator idGen, int genNumber, int workerId) | |||
public GenTest(IIdGenerator idGen, int genIdCount, int workerId) | |||
{ | |||
GenNumber = genNumber; | |||
GenIdCount = genIdCount; | |||
IdGen = idGen; | |||
WorkerId = workerId; | |||
} | |||
public void GenId() | |||
{ | |||
Thread t = new Thread(new ThreadStart(Gen1Start)); | |||
t.Start(); | |||
} | |||
//public void GenId() | |||
//{ | |||
// Thread t = new Thread(new ThreadStart(Gen1Start)); | |||
// t.Start(); | |||
//} | |||
private void Gen1Start() | |||
public void GenStart() | |||
{ | |||
DateTime start = DateTime.Now; | |||
for (int i = 0; i < GenNumber; i++) | |||
for (int i = 0; i < GenIdCount; i++) | |||
{ | |||
var id = IdGen.NewLong(); | |||
//ids.Add(id, i); |
@@ -28,7 +28,7 @@ namespace Yitter.OrgSystem.TestA | |||
while (true) | |||
{ | |||
Go(); | |||
Thread.Sleep(3000); // 每隔3秒执行一次Go | |||
Thread.Sleep(1000); // 每隔3秒执行一次Go | |||
Console.WriteLine("Hello World!"); | |||
} | |||
} | |||
@@ -43,7 +43,7 @@ namespace Yitter.OrgSystem.TestA | |||
Method = method, | |||
WorkerId = 1, | |||
//TopOverCostCount = 2000, | |||
TopOverCostCount = 10000, | |||
//WorkerIdBitLength = 6, | |||
//SeqBitLength = 9, | |||
@@ -56,10 +56,9 @@ namespace Yitter.OrgSystem.TestA | |||
// ++++++++++++++++++++++++++++++++ | |||
if (single) | |||
{ | |||
IdGeneratorOptions options1 = (newConfig); | |||
if (IdGen == null) | |||
{ | |||
IdGen = new DefaultIdGenerator(options1); | |||
IdGen = new DefaultIdGenerator(newConfig); | |||
} | |||
if (outputLog) | |||
@@ -86,7 +85,8 @@ namespace Yitter.OrgSystem.TestA | |||
Console.WriteLine("Gen:" + i); | |||
var test = new GenTest(IdGen, genIdCount, i); | |||
testList.Add(test); | |||
test.GenId(); | |||
// test.GenId(); | |||
test.GenStart(); | |||
} | |||
} | |||
else | |||
@@ -117,7 +117,8 @@ namespace Yitter.OrgSystem.TestA | |||
} | |||
testList.Add(test); | |||
test.GenId(); | |||
// test.GenId(); | |||
test.GenStart(); | |||
} | |||
} | |||
@@ -76,7 +76,6 @@ namespace Yitter.IdGenerator | |||
SeqBitLength = options.SeqBitLength; | |||
MaxSeqNumber = options.MaxSeqNumber; | |||
MinSeqNumber = options.MinSeqNumber; | |||
_CurrentSeqNumber = options.MinSeqNumber; | |||
TopOverCostCount = options.TopOverCostCount; | |||
if (options.StartTime != DateTime.MinValue) | |||
@@ -91,12 +90,12 @@ namespace Yitter.IdGenerator | |||
if (SeqBitLength == 0) | |||
{ | |||
SeqBitLength = 10; | |||
SeqBitLength = 6; | |||
} | |||
if (WorkerIdBitLength == 0) | |||
{ | |||
WorkerIdBitLength = 10; | |||
WorkerIdBitLength = 6; | |||
} | |||
if (MaxSeqNumber == 0) | |||
@@ -105,6 +104,7 @@ namespace Yitter.IdGenerator | |||
} | |||
_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength); | |||
_CurrentSeqNumber = options.MinSeqNumber; | |||
} | |||
@@ -0,0 +1,4 @@ | |||
# idgenerator | |||
something is going on. | |||
@@ -0,0 +1,4 @@ | |||
# idgenerator | |||
something is going on. | |||
@@ -0,0 +1,25 @@ | |||
# Compiled class file | |||
*.class | |||
*.iml | |||
# Log file | |||
*.log | |||
# BlueJ files | |||
*.ctxt | |||
# Mobile Tools for Java (J2ME) | |||
.mtj.tmp/ | |||
# Package Files # | |||
*.jar | |||
*.war | |||
*.nar | |||
*.ear | |||
*.zip | |||
*.tar.gz | |||
*.rar | |||
target/ | |||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | |||
hs_err_pid* |
@@ -0,0 +1,201 @@ | |||
Apache License | |||
Version 2.0, January 2004 | |||
http://www.apache.org/licenses/ | |||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||
1. Definitions. | |||
"License" shall mean the terms and conditions for use, reproduction, | |||
and distribution as defined by Sections 1 through 9 of this document. | |||
"Licensor" shall mean the copyright owner or entity authorized by | |||
the copyright owner that is granting the License. | |||
"Legal Entity" shall mean the union of the acting entity and all | |||
other entities that control, are controlled by, or are under common | |||
control with that entity. For the purposes of this definition, | |||
"control" means (i) the power, direct or indirect, to cause the | |||
direction or management of such entity, whether by contract or | |||
otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||
outstanding shares, or (iii) beneficial ownership of such entity. | |||
"You" (or "Your") shall mean an individual or Legal Entity | |||
exercising permissions granted by this License. | |||
"Source" form shall mean the preferred form for making modifications, | |||
including but not limited to software source code, documentation | |||
source, and configuration files. | |||
"Object" form shall mean any form resulting from mechanical | |||
transformation or translation of a Source form, including but | |||
not limited to compiled object code, generated documentation, | |||
and conversions to other media types. | |||
"Work" shall mean the work of authorship, whether in Source or | |||
Object form, made available under the License, as indicated by a | |||
copyright notice that is included in or attached to the work | |||
(an example is provided in the Appendix below). | |||
"Derivative Works" shall mean any work, whether in Source or Object | |||
form, that is based on (or derived from) the Work and for which the | |||
editorial revisions, annotations, elaborations, or other modifications | |||
represent, as a whole, an original work of authorship. For the purposes | |||
of this License, Derivative Works shall not include works that remain | |||
separable from, or merely link (or bind by name) to the interfaces of, | |||
the Work and Derivative Works thereof. | |||
"Contribution" shall mean any work of authorship, including | |||
the original version of the Work and any modifications or additions | |||
to that Work or Derivative Works thereof, that is intentionally | |||
submitted to Licensor for inclusion in the Work by the copyright owner | |||
or by an individual or Legal Entity authorized to submit on behalf of | |||
the copyright owner. For the purposes of this definition, "submitted" | |||
means any form of electronic, verbal, or written communication sent | |||
to the Licensor or its representatives, including but not limited to | |||
communication on electronic mailing lists, source code control systems, | |||
and issue tracking systems that are managed by, or on behalf of, the | |||
Licensor for the purpose of discussing and improving the Work, but | |||
excluding communication that is conspicuously marked or otherwise | |||
designated in writing by the copyright owner as "Not a Contribution." | |||
"Contributor" shall mean Licensor and any individual or Legal Entity | |||
on behalf of whom a Contribution has been received by Licensor and | |||
subsequently incorporated within the Work. | |||
2. Grant of Copyright License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
copyright license to reproduce, prepare Derivative Works of, | |||
publicly display, publicly perform, sublicense, and distribute the | |||
Work and such Derivative Works in Source or Object form. | |||
3. Grant of Patent License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
(except as stated in this section) patent license to make, have made, | |||
use, offer to sell, sell, import, and otherwise transfer the Work, | |||
where such license applies only to those patent claims licensable | |||
by such Contributor that are necessarily infringed by their | |||
Contribution(s) alone or by combination of their Contribution(s) | |||
with the Work to which such Contribution(s) was submitted. If You | |||
institute patent litigation against any entity (including a | |||
cross-claim or counterclaim in a lawsuit) alleging that the Work | |||
or a Contribution incorporated within the Work constitutes direct | |||
or contributory patent infringement, then any patent licenses | |||
granted to You under this License for that Work shall terminate | |||
as of the date such litigation is filed. | |||
4. Redistribution. You may reproduce and distribute copies of the | |||
Work or Derivative Works thereof in any medium, with or without | |||
modifications, and in Source or Object form, provided that You | |||
meet the following conditions: | |||
(a) You must give any other recipients of the Work or | |||
Derivative Works a copy of this License; and | |||
(b) You must cause any modified files to carry prominent notices | |||
stating that You changed the files; and | |||
(c) You must retain, in the Source form of any Derivative Works | |||
that You distribute, all copyright, patent, trademark, and | |||
attribution notices from the Source form of the Work, | |||
excluding those notices that do not pertain to any part of | |||
the Derivative Works; and | |||
(d) If the Work includes a "NOTICE" text file as part of its | |||
distribution, then any Derivative Works that You distribute must | |||
include a readable copy of the attribution notices contained | |||
within such NOTICE file, excluding those notices that do not | |||
pertain to any part of the Derivative Works, in at least one | |||
of the following places: within a NOTICE text file distributed | |||
as part of the Derivative Works; within the Source form or | |||
documentation, if provided along with the Derivative Works; or, | |||
within a display generated by the Derivative Works, if and | |||
wherever such third-party notices normally appear. The contents | |||
of the NOTICE file are for informational purposes only and | |||
do not modify the License. You may add Your own attribution | |||
notices within Derivative Works that You distribute, alongside | |||
or as an addendum to the NOTICE text from the Work, provided | |||
that such additional attribution notices cannot be construed | |||
as modifying the License. | |||
You may add Your own copyright statement to Your modifications and | |||
may provide additional or different license terms and conditions | |||
for use, reproduction, or distribution of Your modifications, or | |||
for any such Derivative Works as a whole, provided Your use, | |||
reproduction, and distribution of the Work otherwise complies with | |||
the conditions stated in this License. | |||
5. Submission of Contributions. Unless You explicitly state otherwise, | |||
any Contribution intentionally submitted for inclusion in the Work | |||
by You to the Licensor shall be under the terms and conditions of | |||
this License, without any additional terms or conditions. | |||
Notwithstanding the above, nothing herein shall supersede or modify | |||
the terms of any separate license agreement you may have executed | |||
with Licensor regarding such Contributions. | |||
6. Trademarks. This License does not grant permission to use the trade | |||
names, trademarks, service marks, or product names of the Licensor, | |||
except as required for reasonable and customary use in describing the | |||
origin of the Work and reproducing the content of the NOTICE file. | |||
7. Disclaimer of Warranty. Unless required by applicable law or | |||
agreed to in writing, Licensor provides the Work (and each | |||
Contributor provides its Contributions) on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||
implied, including, without limitation, any warranties or conditions | |||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||
PARTICULAR PURPOSE. You are solely responsible for determining the | |||
appropriateness of using or redistributing the Work and assume any | |||
risks associated with Your exercise of permissions under this License. | |||
8. Limitation of Liability. In no event and under no legal theory, | |||
whether in tort (including negligence), contract, or otherwise, | |||
unless required by applicable law (such as deliberate and grossly | |||
negligent acts) or agreed to in writing, shall any Contributor be | |||
liable to You for damages, including any direct, indirect, special, | |||
incidental, or consequential damages of any character arising as a | |||
result of this License or out of the use or inability to use the | |||
Work (including but not limited to damages for loss of goodwill, | |||
work stoppage, computer failure or malfunction, or any and all | |||
other commercial damages or losses), even if such Contributor | |||
has been advised of the possibility of such damages. | |||
9. Accepting Warranty or Additional Liability. While redistributing | |||
the Work or Derivative Works thereof, You may choose to offer, | |||
and charge a fee for, acceptance of support, warranty, indemnity, | |||
or other liability obligations and/or rights consistent with this | |||
License. However, in accepting such obligations, You may act only | |||
on Your own behalf and on Your sole responsibility, not on behalf | |||
of any other Contributor, and only if You agree to indemnify, | |||
defend, and hold each Contributor harmless for any liability | |||
incurred by, or claims asserted against, such Contributor by reason | |||
of your accepting any such warranty or additional liability. | |||
END OF TERMS AND CONDITIONS | |||
APPENDIX: How to apply the Apache License to your work. | |||
To apply the Apache License to your work, attach the following | |||
boilerplate notice, with the fields enclosed by brackets "[]" | |||
replaced with your own identifying information. (Don't include | |||
the brackets!) The text should be enclosed in the appropriate | |||
comment syntax for the file format. We also recommend that a | |||
file or class name and description of purpose be included on the | |||
same "printed page" as the copyright notice for easier | |||
identification within third-party archives. | |||
Copyright [yyyy] [name of copyright owner] | |||
Licensed under the Apache License, Version 2.0 (the "License"); | |||
you may not use this file except in compliance with the License. | |||
You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. |
@@ -0,0 +1,93 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<groupId>com.yitter</groupId> | |||
<artifactId>yitter.idgenerator</artifactId> | |||
<packaging>jar</packaging> | |||
<version>1.0.0</version> | |||
<name>yitter.idgenerator</name> | |||
<description>Shorter ID and faster generation with a new snowflake drift algorithm. The core is to shorten the ID length, but also can have a very high instantaneous concurrent processing capacity (50W/0.1s), and powerful configuration capacity.</description> | |||
<developers> | |||
<developer> | |||
<id>yitter</id> | |||
<name>yitter</name> | |||
<email>yitter@126.com</email> | |||
<url>https://gitee.com/yitter/idgenerator</url> | |||
</developer> | |||
</developers> | |||
<properties> | |||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||
<maven.compiler.source>1.8</maven.compiler.source> | |||
<maven.compiler.target>1.8</maven.compiler.target> | |||
<java.version>1.8</java.version> | |||
</properties> | |||
<build> | |||
<pluginManagement> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.8.0</version> | |||
<configuration> | |||
<source>${java.version}</source> | |||
<target>${java.version}</target> | |||
<encoding>UTF-8</encoding> | |||
</configuration> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-jar-plugin</artifactId> | |||
<version>3.1.0</version> | |||
</plugin> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-surefire-plugin</artifactId> | |||
<configuration> | |||
<skip>true</skip> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</pluginManagement> | |||
<resources> | |||
<resource> | |||
<directory>${project.basedir}</directory> | |||
<targetPath>META-INF</targetPath> | |||
<includes> | |||
<include>LICENSE</include> | |||
<include>NOTICE</include> | |||
</includes> | |||
</resource> | |||
<resource> | |||
<directory>src/main/resources</directory> | |||
<filtering>true</filtering> | |||
<includes> | |||
<include>**</include> | |||
</includes> | |||
</resource> | |||
</resources> | |||
<testResources> | |||
<testResource> | |||
<directory>src/test/resources</directory> | |||
<includes> | |||
<include>**</include> | |||
</includes> | |||
</testResource> | |||
</testResources> | |||
</build> | |||
<licenses> | |||
<license> | |||
<name>The Apache Software License, Version 2.0</name> | |||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> | |||
</license> | |||
</licenses> | |||
</project> |
@@ -0,0 +1,9 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.contract; | |||
public interface IIdGenerator { | |||
long newLong() throws IdGeneratorException; | |||
} |
@@ -0,0 +1,9 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.contract; | |||
public interface ISnowWorker { | |||
long nextId() throws IdGeneratorException; | |||
} |
@@ -0,0 +1,28 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.contract; | |||
public class IdGeneratorException extends RuntimeException { | |||
public IdGeneratorException() { | |||
super(); | |||
} | |||
public IdGeneratorException(String message) { | |||
super(message); | |||
} | |||
public IdGeneratorException(Throwable cause) { | |||
super(cause); | |||
} | |||
public IdGeneratorException(String message, Throwable cause) { | |||
super(message, cause); | |||
} | |||
public IdGeneratorException(String msgFormat, Object... args) { | |||
super(String.format(msgFormat, args)); | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.contract; | |||
/** | |||
* 雪花算法使用的参数 | |||
* 此处代码不采用 get/set 那种冗长的写法 | |||
*/ | |||
public class IdGeneratorOptions { | |||
/** | |||
* 雪花计算方法 | |||
* (1-漂移算法|2-传统算法),默认1 | |||
*/ | |||
public short Method = 1; | |||
/** | |||
* 开始时间 | |||
* 不能超过当前系统时间 | |||
*/ | |||
public long StartTime = 0; | |||
/** | |||
* 机器码,必须由外部系统设置 | |||
* 与 WorkerIdBitLength 有关系 | |||
*/ | |||
public short WorkerId = 0; | |||
/** | |||
* 机器码位长 | |||
* 范围:2-21(要求:序列数位长+机器码位长不超过22)。 | |||
* 建议范围:6-12。 | |||
*/ | |||
public byte WorkerIdBitLength = 6; | |||
/** | |||
* 序列数位长 | |||
* 范围:2-21(要求:序列数位长+机器码位长不超过22)。 | |||
* 建议范围:6-14。 | |||
*/ | |||
public byte SeqBitLength = 6; | |||
/** | |||
* 最大序列数(含) | |||
* (由SeqBitLength计算的最大值) | |||
*/ | |||
public short MaxSeqNumber = 0; | |||
/** | |||
* 最小序列数(含) | |||
* 默认11,不小于5,不大于MaxSeqNumber-2 | |||
*/ | |||
public short MinSeqNumber = 11; | |||
/** | |||
* 最大漂移次数(含) | |||
* 默认2000,推荐范围500-10000(与计算能力有关) | |||
*/ | |||
public short TopOverCostCount = 2000; | |||
public IdGeneratorOptions() { | |||
} | |||
public IdGeneratorOptions(short workerId) { | |||
WorkerId = workerId; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.contract; | |||
/** | |||
* Id生成时回调参数 | |||
*/ | |||
public class OverCostActionArg { | |||
/** | |||
* 事件类型 | |||
* 1-开始,2-结束,8-漂移 | |||
*/ | |||
public int ActionType = 0; | |||
/** | |||
* 时间戳 | |||
*/ | |||
public long TimeTick = 0; | |||
/** | |||
* 机器码 | |||
*/ | |||
public short WorkerId = 0; | |||
/** | |||
* | |||
*/ | |||
public int OverCostCountInOneTerm = 0; | |||
/** | |||
* 漂移期间生产ID个数 | |||
*/ | |||
public int GenCountInOneTerm = 0; | |||
/** | |||
* 漂移周期 | |||
*/ | |||
public int TermIndex = 0; | |||
public OverCostActionArg(short workerId, long timeTick, int actionType, int overCostCountInOneTerm, int genCountWhenOverCost, int index) { | |||
ActionType = actionType; | |||
TimeTick = timeTick; | |||
WorkerId = workerId; | |||
OverCostCountInOneTerm = overCostCountInOneTerm; | |||
GenCountInOneTerm = genCountWhenOverCost; | |||
TermIndex = index; | |||
} | |||
} |
@@ -0,0 +1,247 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.core; | |||
import com.yitter.contract.ISnowWorker; | |||
import com.yitter.contract.IdGeneratorException; | |||
import com.yitter.contract.IdGeneratorOptions; | |||
import com.yitter.contract.OverCostActionArg; | |||
public class SnowWorkerM1 implements ISnowWorker { | |||
/** | |||
* 基础时间 | |||
*/ | |||
protected final long StartTimeUtc; | |||
/** | |||
* 机器码 | |||
*/ | |||
protected final short WorkerId; | |||
/** | |||
* 机器码位长 | |||
* (机器码+序列数<=22位) | |||
*/ | |||
protected final byte WorkerIdBitLength; | |||
/** | |||
* 自增序列数位长 | |||
* (机器码+序列数<=22位) | |||
*/ | |||
protected final byte SeqBitLength; | |||
/** | |||
* 最大序列数(含此值) | |||
* 超过最大值,就会从MinSeqNumber开始 | |||
*/ | |||
protected final int MaxSeqNumber; | |||
/** | |||
* 最小序列数(含此值) | |||
*/ | |||
protected final short MinSeqNumber; | |||
/** | |||
* 最大漂移次数 | |||
*/ | |||
protected final int TopOverCostCount; | |||
protected final byte _TimestampShift; | |||
protected final static byte[] _SyncLock = new byte[0]; | |||
protected short _CurrentSeqNumber; | |||
protected long _LastTimeTick = -1L; | |||
protected long _TurnBackTimeTick = -1L; | |||
protected boolean _IsOverCost = false; | |||
protected int _OverCostCountInOneTerm = 0; | |||
protected int _GenCountInOneTerm = 0; | |||
protected int _TermIndex = 0; | |||
public SnowWorkerM1(IdGeneratorOptions options) { | |||
WorkerId = options.WorkerId; | |||
WorkerIdBitLength = options.WorkerIdBitLength == 0 ? 6 : options.WorkerIdBitLength; | |||
SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength; | |||
MaxSeqNumber = options.MaxSeqNumber > 0 ? options.MaxSeqNumber : (int) Math.pow(2, SeqBitLength); | |||
MinSeqNumber = options.MinSeqNumber; | |||
TopOverCostCount = options.TopOverCostCount; | |||
StartTimeUtc = options.StartTime != 0 ? options.StartTime : 1582136402000L; | |||
_TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength); | |||
_CurrentSeqNumber = options.MinSeqNumber; | |||
} | |||
private void DoGenIdAction(OverCostActionArg arg) { | |||
} | |||
private void BeginOverCostCallBack(long useTimeTick) { | |||
// if (GenAction == null) { | |||
// return; | |||
// } | |||
// | |||
// DoGenIdAction(new OverCostActionArg( | |||
// WorkerId, | |||
// useTimeTick, | |||
// 1, | |||
// _OverCostCountInOneTerm, | |||
// _GenCountInOneTerm, | |||
// _TermIndex)); | |||
} | |||
private void EndOverCostCallBack(long useTimeTick) { | |||
if (_TermIndex > 10000) { | |||
_TermIndex = 0; | |||
} | |||
// | |||
// if (GenAction == null) { | |||
// return; | |||
// } | |||
// | |||
// DoGenIdAction(new OverCostActionArg( | |||
// WorkerId, | |||
// useTimeTick, | |||
// 2, | |||
// _OverCostCountInOneTerm, | |||
// _GenCountInOneTerm, | |||
// _TermIndex)); | |||
} | |||
private void TurnBackCallBack(long useTimeTick) { | |||
// if (GenAction == null) { | |||
// return; | |||
// } | |||
// | |||
// DoGenIdAction(new OverCostActionArg( | |||
// WorkerId, | |||
// useTimeTick, | |||
// 8, | |||
// _OverCostCountInOneTerm, | |||
// _GenCountInOneTerm, | |||
// _TermIndex)); | |||
} | |||
private long NextOverCostId() { | |||
long currentTimeTick = GetCurrentTimeTick(); | |||
if (currentTimeTick > _LastTimeTick) { | |||
EndOverCostCallBack(currentTimeTick); | |||
_LastTimeTick = currentTimeTick; | |||
_CurrentSeqNumber = MinSeqNumber; | |||
_IsOverCost = false; | |||
_OverCostCountInOneTerm = 0; | |||
_GenCountInOneTerm = 0; | |||
return CalcId(_LastTimeTick); | |||
} | |||
if (_OverCostCountInOneTerm >= TopOverCostCount) { | |||
EndOverCostCallBack(currentTimeTick); | |||
_LastTimeTick = GetNextTimeTick(); | |||
_CurrentSeqNumber = MinSeqNumber; | |||
_IsOverCost = false; | |||
_OverCostCountInOneTerm = 0; | |||
_GenCountInOneTerm = 0; | |||
return CalcId(_LastTimeTick); | |||
} | |||
if (_CurrentSeqNumber > MaxSeqNumber) { | |||
_LastTimeTick++; | |||
_CurrentSeqNumber = MinSeqNumber; | |||
_IsOverCost = true; | |||
_OverCostCountInOneTerm++; | |||
_GenCountInOneTerm++; | |||
return CalcId(_LastTimeTick); | |||
} | |||
_GenCountInOneTerm++; | |||
return CalcId(_LastTimeTick); | |||
} | |||
private long NextNormalId() throws IdGeneratorException { | |||
long currentTimeTick = GetCurrentTimeTick(); | |||
if (currentTimeTick > _LastTimeTick) { | |||
_LastTimeTick = currentTimeTick; | |||
_CurrentSeqNumber = MinSeqNumber; | |||
return CalcId(_LastTimeTick); | |||
} | |||
if (_CurrentSeqNumber > MaxSeqNumber) { | |||
BeginOverCostCallBack(currentTimeTick); | |||
_TermIndex++; | |||
_LastTimeTick++; | |||
_CurrentSeqNumber = MinSeqNumber; | |||
_IsOverCost = true; | |||
_OverCostCountInOneTerm++; | |||
_GenCountInOneTerm = 1; | |||
return CalcId(_LastTimeTick); | |||
} | |||
if (currentTimeTick < _LastTimeTick) { | |||
if (_TurnBackTimeTick < 1) { | |||
_TurnBackTimeTick = _LastTimeTick - 1; | |||
} | |||
try { | |||
Thread.sleep(10); | |||
} catch (InterruptedException e) { | |||
e.printStackTrace(); | |||
} | |||
TurnBackCallBack(_TurnBackTimeTick); | |||
return CalcTurnBackId(_TurnBackTimeTick); | |||
} | |||
return CalcId(_LastTimeTick); | |||
} | |||
private long CalcId(long useTimeTick) { | |||
long result = ((useTimeTick << _TimestampShift) + | |||
((long) WorkerId << SeqBitLength) + | |||
(int) _CurrentSeqNumber); | |||
_CurrentSeqNumber++; | |||
return result; | |||
} | |||
private long CalcTurnBackId(long useTimeTick) { | |||
long result = ((useTimeTick << _TimestampShift) + | |||
((long) WorkerId << SeqBitLength) + 0); | |||
_TurnBackTimeTick--; | |||
return result; | |||
} | |||
protected long GetCurrentTimeTick() { | |||
long millis = System.currentTimeMillis(); | |||
return millis - StartTimeUtc; | |||
} | |||
protected long GetNextTimeTick() { | |||
long tempTimeTicker = GetCurrentTimeTick(); | |||
while (tempTimeTicker <= _LastTimeTick) { | |||
tempTimeTicker = GetCurrentTimeTick(); | |||
} | |||
return tempTimeTicker; | |||
} | |||
@Override | |||
public long nextId() { | |||
synchronized (_SyncLock) { | |||
return _IsOverCost ? NextOverCostId() : NextNormalId(); | |||
} | |||
} | |||
} | |||
@@ -0,0 +1,41 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.core; | |||
import com.yitter.contract.IdGeneratorException; | |||
import com.yitter.contract.IdGeneratorOptions; | |||
public class SnowWorkerM2 extends SnowWorkerM1 { | |||
public SnowWorkerM2(IdGeneratorOptions options) { | |||
super(options); | |||
} | |||
@Override | |||
public long nextId() { | |||
synchronized (_SyncLock) { | |||
long currentTimeTick = GetCurrentTimeTick(); | |||
if (_LastTimeTick == currentTimeTick) { | |||
if (_CurrentSeqNumber++ > MaxSeqNumber) { | |||
_CurrentSeqNumber = MinSeqNumber; | |||
currentTimeTick = GetNextTimeTick(); | |||
} | |||
} else { | |||
_CurrentSeqNumber = MinSeqNumber; | |||
} | |||
if (currentTimeTick < _LastTimeTick) { | |||
throw new IdGeneratorException("Time error for {0} milliseconds", _LastTimeTick - currentTimeTick); | |||
} | |||
_LastTimeTick = currentTimeTick; | |||
long result = ((currentTimeTick << _TimestampShift) + ((long) WorkerId << SeqBitLength) + (int) _CurrentSeqNumber); | |||
return result; | |||
} | |||
} | |||
} |
@@ -0,0 +1,85 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.idgen; | |||
import com.yitter.contract.ISnowWorker; | |||
import com.yitter.contract.IdGeneratorException; | |||
import com.yitter.contract.IdGeneratorOptions; | |||
import com.yitter.contract.IIdGenerator; | |||
import com.yitter.core.SnowWorkerM1; | |||
import com.yitter.core.SnowWorkerM2; | |||
public class DefaultIdGenerator implements IIdGenerator { | |||
private final ISnowWorker _SnowWorker; | |||
public DefaultIdGenerator(IdGeneratorOptions options) throws IdGeneratorException { | |||
if (options == null) | |||
{ | |||
throw new IdGeneratorException("options error."); | |||
} | |||
if (options.StartTime > System.currentTimeMillis()) | |||
{ | |||
throw new IdGeneratorException("StartTime error."); | |||
} | |||
if (options.SeqBitLength + options.WorkerIdBitLength > 22) | |||
{ | |||
throw new IdGeneratorException("error:WorkerIdBitLength + SeqBitLength <= 22"); | |||
} | |||
double maxWorkerIdNumber = Math.pow(2, options.WorkerIdBitLength) - 1; | |||
if (options.WorkerId < 1 || options.WorkerId > maxWorkerIdNumber) | |||
{ | |||
throw new IdGeneratorException("WorkerId error. (range:[1, " + maxWorkerIdNumber + "]"); | |||
} | |||
if (options.SeqBitLength < 2 || options.SeqBitLength > 21) | |||
{ | |||
throw new IdGeneratorException("SeqBitLength error. (range:[2, 21])"); | |||
} | |||
double maxSeqNumber = Math.pow(2, options.SeqBitLength) - 1; | |||
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber) | |||
{ | |||
throw new IdGeneratorException("MaxSeqNumber error. (range:[1, " + maxSeqNumber + "]"); | |||
} | |||
double maxValue = maxSeqNumber - 2; | |||
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxValue) | |||
{ | |||
throw new IdGeneratorException("MinSeqNumber error. (range:[5, " + maxValue + "]"); | |||
} | |||
switch (options.Method) | |||
{ | |||
case 1: | |||
_SnowWorker = new SnowWorkerM1(options); | |||
break; | |||
case 2: | |||
_SnowWorker = new SnowWorkerM2(options); | |||
break; | |||
default: | |||
_SnowWorker = new SnowWorkerM1(options); | |||
break; | |||
} | |||
if (options.Method == 1) | |||
{ | |||
try { | |||
Thread.sleep(500); | |||
} catch (InterruptedException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
} | |||
@Override | |||
public long newLong() { | |||
return _SnowWorker.nextId(); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* 版权属于:yitter(yitter@126.com) | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package com.yitter.idgen; | |||
import com.yitter.contract.IdGeneratorException; | |||
import com.yitter.contract.IdGeneratorOptions; | |||
import com.yitter.contract.IIdGenerator; | |||
/** | |||
* 这是一个调用的例子,默认情况下,单机集成者可以直接使用 NewId()。 | |||
*/ | |||
public class IdHelper { | |||
private static IIdGenerator idGenInstance = null; | |||
public static IIdGenerator getIdGenInstance() | |||
{ | |||
return idGenInstance; | |||
} | |||
/** | |||
* 设置参数,建议程序初始化时执行一次 | |||
* @param options | |||
*/ | |||
public static void setIdGenerator(IdGeneratorOptions options) throws IdGeneratorException { | |||
idGenInstance = new DefaultIdGenerator(options); | |||
} | |||
/** | |||
* 生成新的Id | |||
* 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。 | |||
* @return | |||
*/ | |||
public static long nextId() throws IdGeneratorException { | |||
if (idGenInstance == null) | |||
{ | |||
idGenInstance = new DefaultIdGenerator(new IdGeneratorOptions((short)1)); | |||
} | |||
return idGenInstance.newLong(); | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
package com.yitter.test; | |||
import com.yitter.contract.IIdGenerator; | |||
public class GenTest { | |||
private IIdGenerator IdGen; | |||
private int GenIdCount; | |||
private int WorkerId; | |||
public GenTest(IIdGenerator idGen, int genIdCount, int workerId) { | |||
GenIdCount = genIdCount; | |||
IdGen = idGen; | |||
WorkerId = workerId; | |||
} | |||
public void GenStart() { | |||
long start = System.currentTimeMillis(); | |||
for (int i = 0; i < GenIdCount; i++) { | |||
long id = IdGen.newLong(); | |||
} | |||
long end = System.currentTimeMillis(); | |||
long time = end - start; | |||
System.out.println("++++++++++++++++++++++++++++++++++++++++WorkerId: " | |||
+ WorkerId + ", total: " + time + " ms"); | |||
} | |||
} |
@@ -0,0 +1,57 @@ | |||
package com.yitter.test; | |||
import com.yitter.contract.IdGeneratorOptions; | |||
import com.yitter.contract.IIdGenerator; | |||
import com.yitter.idgen.DefaultIdGenerator; | |||
import com.yitter.idgen.IdHelper; | |||
public class StartUp { | |||
/** | |||
* 测试结果: | |||
* (1):1W并发,方法 1只要 1ms.而方法 2 要 180ms。 | |||
* (2):5W并发,方法 1只要 9ms.而方法 2 要 900ms。 | |||
* [不同CPU可能结果有差异,但相对大小不变] | |||
* 默认配置下,最佳性能是5W/s-8W/s | |||
*/ | |||
final static int genIdCount = 50000; | |||
//1-漂移算法,2-传统算法 | |||
final static short method = 1; | |||
public static void main(String[] args) { | |||
IdGeneratorOptions options = new IdGeneratorOptions(); | |||
//options.TopOverCostCount = 10000; | |||
// options.WorkerIdBitLength = 6; | |||
// options.SeqBitLength = 9; | |||
// options.MinSeqNumber = 11; | |||
// options.MaxSeqNumber = 200; | |||
options.Method = method; | |||
options.WorkerId = 1; | |||
options.StartTime = 1582206693000L; // (2020-2-20) | |||
IIdGenerator IdGen = new DefaultIdGenerator(options); | |||
GenTest genTest = new GenTest(IdGen, genIdCount, options.WorkerId); | |||
// 首先测试一下 IdHelper 方法,获取单个Id | |||
IdHelper.setIdGenerator(options); | |||
long newId = IdHelper.nextId(); | |||
System.out.println("====================================="); | |||
System.out.println("这是用方法 " + method + " 生成的 Id:" + newId); | |||
// 然后循环测试一下,看看并发请求时的耗时情况 | |||
try { | |||
while (true) { | |||
genTest.GenStart(); | |||
Thread.sleep(1000); // 每隔1秒执行一次GenStart | |||
System.out.println("Hello World!"); | |||
} | |||
} catch (InterruptedException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,4 @@ | |||
# idgenerator | |||
something is going on. | |||