├── .gitignore ├── LICENSE ├── README.md ├── filetest.txt ├── mkdirs └── test │ └── filetest.txt ├── output.xml ├── pom.xml ├── readandshow.txt ├── src ├── main │ ├── java │ │ └── zhongqiu │ │ │ └── common │ │ │ ├── base │ │ │ ├── BaseTypeDemo.java │ │ │ ├── DateDemo.java │ │ │ ├── EnumerationDemo.java │ │ │ ├── FileIODemo.java │ │ │ ├── FinalDemo.java │ │ │ ├── InnerClassDemo.java │ │ │ ├── MathRandomDemo.java │ │ │ ├── NetDemo.java │ │ │ ├── NumberDemo.java │ │ │ ├── OperatorDemo.java │ │ │ ├── Reflection.java │ │ │ ├── RegexDemo.java │ │ │ ├── SendMailDemo.java │ │ │ ├── SerializeDemo.java │ │ │ ├── StringDemo.java │ │ │ ├── SwitchDemo.java │ │ │ ├── ThrowableDemo.java │ │ │ ├── algorithm │ │ │ │ ├── BinaryTreeUtil.java │ │ │ │ ├── LinkedList.java │ │ │ │ ├── dynamicplanning │ │ │ │ │ ├── BestLoading.java │ │ │ │ │ ├── knapsack.java │ │ │ │ │ └── package-info.java │ │ │ │ ├── package-info.java │ │ │ │ ├── programming │ │ │ │ │ ├── CrazyQueue.java │ │ │ │ │ ├── ErrorRecords.java │ │ │ │ │ ├── FindFirstOnceOccurCharactar.java │ │ │ │ │ ├── FindSubString.java │ │ │ │ │ ├── LexicographicOrder.java │ │ │ │ │ ├── StringBigNumberMulti.java │ │ │ │ │ ├── TestDistribution.java │ │ │ │ │ ├── Tree.java │ │ │ │ │ └── swordatoffer │ │ │ │ │ │ ├── Fibonacci.java │ │ │ │ │ │ ├── OrderedArraySearch.java │ │ │ │ │ │ ├── ReplaceSpace.java │ │ │ │ │ │ ├── RevolvingArray.java │ │ │ │ │ │ └── TwoStackReplaceQueen.java │ │ │ │ ├── search │ │ │ │ │ ├── BinarySearch.java │ │ │ │ │ └── SequentialSearch.java │ │ │ │ └── sort │ │ │ │ │ ├── BubbleSort.java │ │ │ │ │ ├── HeapSort.java │ │ │ │ │ ├── InsertSort.java │ │ │ │ │ ├── MergeSort.java │ │ │ │ │ └── QuickSort.java │ │ │ ├── applet │ │ │ │ ├── AppletDemo.java │ │ │ │ ├── AppletTest.html │ │ │ │ └── package-info.java │ │ │ ├── collections │ │ │ │ ├── ArrayDemo.java │ │ │ │ ├── ArraysDemo.java │ │ │ │ ├── CollectionPo.java │ │ │ │ ├── CollectionsDemo.java │ │ │ │ ├── ListDemo.java │ │ │ │ ├── MapDemo.java │ │ │ │ ├── SetDemo.java │ │ │ │ ├── StackDemo.java │ │ │ │ └── package-info.java │ │ │ ├── gc │ │ │ │ ├── GCCollector.java │ │ │ │ └── classload │ │ │ │ │ ├── ClassLoadDemo.java │ │ │ │ │ ├── MyClassLoader.java │ │ │ │ │ ├── Test.java │ │ │ │ │ └── package-info.java │ │ │ ├── nio │ │ │ │ ├── CopyFile.java │ │ │ │ ├── CreateArrayBuffer.java │ │ │ │ ├── CreateBuffer.java │ │ │ │ ├── FastCopyFile.java │ │ │ │ ├── MultiPortEcho.java │ │ │ │ ├── ReadAndShow.java │ │ │ │ ├── SliceBuffer.java │ │ │ │ ├── TypesInByteBuffer.java │ │ │ │ ├── UseCharsets.java │ │ │ │ ├── UseFileLocks.java │ │ │ │ ├── UseFloatBuffer.java │ │ │ │ ├── UseMappedFile.java │ │ │ │ ├── UseScatterGather.java │ │ │ │ ├── WriteSomeBytes.java │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ └── thread │ │ │ │ ├── CallableTest.java │ │ │ │ ├── MultiThreadDemo.java │ │ │ │ ├── PrintABC.java │ │ │ │ ├── SimpleDateFormatDemo.java │ │ │ │ ├── SynchronizedDemo.java │ │ │ │ ├── ThreadDemo.java │ │ │ │ ├── ThreadLocalDemo.java │ │ │ │ ├── VolatileDemo.java │ │ │ │ ├── VolatileDemo2.java │ │ │ │ ├── WaitNotifyDemo.java │ │ │ │ └── package-info.java │ │ │ ├── jdk5 │ │ │ ├── Boxing.java │ │ │ ├── EnumDemo.java │ │ │ ├── GenericsDemo.java │ │ │ ├── Introspector.java │ │ │ ├── PrintABCTest.java │ │ │ ├── ScannerDemo.java │ │ │ ├── VarableParameter.java │ │ │ ├── concurrent │ │ │ │ ├── BlockingQueueDemo.java │ │ │ │ ├── ConcurrentHashMapDemo.java │ │ │ │ ├── CountDownLatchDemo.java │ │ │ │ ├── CyclicBarrierDemo.java │ │ │ │ ├── ExchangerDemo.java │ │ │ │ ├── ExecutorsDemo.java │ │ │ │ ├── FutureTaskDemo.java │ │ │ │ ├── ScheduledThreadPoolExecutorDemo.java │ │ │ │ ├── SemaphoreDemo.java │ │ │ │ ├── ThreadPoolExecutorDemo.java │ │ │ │ ├── atomic │ │ │ │ │ ├── AtomicBooleanDemo.java │ │ │ │ │ ├── AtomicIntegerArrayDemo.java │ │ │ │ │ ├── AtomicIntegerDemo.java │ │ │ │ │ ├── AtomicIntegerFieldUpdaterDemo.java │ │ │ │ │ ├── AtomicMarkableReferenceDemo.java │ │ │ │ │ ├── AtomicReferenceDemo.java │ │ │ │ │ ├── AtomicStampedReferenceDemo.java │ │ │ │ │ └── package-info.java │ │ │ │ ├── locks │ │ │ │ │ ├── LockSupportDemo.java │ │ │ │ │ ├── ReentrantLockDemo.java │ │ │ │ │ ├── ReentrantReadWriteLockDemo.java │ │ │ │ │ └── package-info.java │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ └── util │ │ │ │ └── PriorityQueueDemo.java │ │ │ ├── jdk6 │ │ │ ├── AnnotationDemo.java │ │ │ ├── CompilerAPIDemo.java │ │ │ ├── ConsoleDemo.java │ │ │ ├── HttpServerAPIDemo.java │ │ │ ├── ScriptDemo.java │ │ │ ├── StaxDemo.java │ │ │ └── package-info.java │ │ │ ├── jdk7 │ │ │ ├── BinaryDemo.java │ │ │ ├── ColletionsDemo.java │ │ │ ├── GetEnvironmentDemo.java │ │ │ ├── TryCatchDemo.java │ │ │ ├── TypeInferenceDemo.java │ │ │ ├── ValueWithUnderline.java │ │ │ ├── VarableParameter.java │ │ │ ├── concurrent │ │ │ │ ├── ForkJoinTaskDemo.java │ │ │ │ ├── TransferQueueDemo.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ ├── jdk8 │ │ │ ├── DateAPIDemo.java │ │ │ ├── FI.java │ │ │ ├── InterfaceDefaultMethod.java │ │ │ ├── Lambda.java │ │ │ ├── OptionalDemo.java │ │ │ ├── StringJoinDemo.java │ │ │ ├── TargetType.java │ │ │ └── package-info.java │ │ │ └── utils │ │ │ └── CommonUtils.java │ └── resources │ │ └── SortCompare.png └── test │ └── java │ └── zhongqiu │ └── common │ └── test │ ├── CodeBlock03.java │ ├── Main.java │ ├── test.java │ ├── test1.java │ ├── test2.java │ ├── test3.java │ ├── test4.java │ └── test5.java ├── test.xml ├── usefilelocks.txt └── writesomebytes.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.DS_Store 3 | *.lock 4 | *.swp 5 | .settings 6 | target 7 | bin 8 | .classpath 9 | .project 10 | .idea 11 | *.eml 12 | *.iml 13 | .build 14 | rebel.xml 15 | hb-* 16 | fj-* 17 | .classpath 18 | node_modules 19 | /.externalToolBuilders/ 20 | *.tmp 21 | release.properties 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaCommon 2 | Java基础用法,集合,线程,JUC,jdk5--8各个版本特性。代码示例和源码分析 3 | 每个包的package-info.java有详细的说明和参考资料 4 | -------------------------------------------------------------------------------- /filetest.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leon66666/JavaCommon/4af0fc8f1de2c86e4bfdd0d7d12f1b6308e9b9b0/filetest.txt -------------------------------------------------------------------------------- /mkdirs/test/filetest.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leon66666/JavaCommon/4af0fc8f1de2c86e4bfdd0d7d12f1b6308e9b9b0/mkdirs/test/filetest.txt -------------------------------------------------------------------------------- /output.xml: -------------------------------------------------------------------------------- 1 | Apparel -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | zhongqiu 8 | javacommon 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 1.8 17 | 1.8 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /readandshow.txt: -------------------------------------------------------------------------------- 1 | sdfggs -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/DateDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | //Date相关 7 | //http://www.runoob.com/java/java-date-time.html 8 | public class DateDemo { 9 | public static void main(String[] args) { 10 | simpleDateFormat(); 11 | } 12 | 13 | // 使用 SimpleDateFormat 格式化日期 14 | public static void simpleDateFormat() { 15 | Date dNow = new Date(); 16 | 17 | SimpleDateFormat ft = new SimpleDateFormat("E yyyy.MM.dd 'at' hh:mm:ss a zzz"); 18 | System.out.println("Current Date: " + ft.format(dNow)); 19 | 20 | SimpleDateFormat ft1 = new SimpleDateFormat("yyyy.MM.dd 'at' hh:mm:ss a zzz"); 21 | System.out.println("Current Date: " + ft1.format(dNow)); 22 | 23 | SimpleDateFormat ft2 = new SimpleDateFormat("yyyy.MM.dd 'at' hh:mm:ss"); 24 | System.out.println("Current Date: " + ft2.format(dNow)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/EnumerationDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | import java.util.Enumeration; 4 | 5 | public class EnumerationDemo implements Enumeration{ 6 | int count; // 计数器 7 | int length; //存储的数组的长度 8 | Object[] dataArray; // 存储数据数组的引用 9 | //构造器 10 | EnumerationDemo(int count,int length,Object[] dataArray){ 11 | this.count = count; 12 | this.length= length; 13 | this.dataArray=dataArray; 14 | } 15 | public boolean hasMoreElements() { 16 | return (count< length); 17 | } 18 | public Object nextElement() { 19 | return dataArray[count++]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/FileIODemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.FileOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStreamReader; 9 | import java.io.OutputStreamWriter; 10 | 11 | //流(Stream)、文件(File)和IO 12 | //http://www.runoob.com/java/java-files-io.html 13 | public class FileIODemo { 14 | public static void main(String[] args) { 15 | // BRRead(); 16 | // BRReadLine(); 17 | // Write(); 18 | 19 | mkdirs(); 20 | fileStream(); 21 | dirList("mkdirs"); 22 | } 23 | 24 | // 读取输入的字符 25 | public static void BRRead() { 26 | char c = 0; 27 | // 使用 System.in 创建 BufferedReader 28 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 29 | System.out.println("输入字符, 按下 'q' 键退出。"); 30 | // 读取字符 31 | do { 32 | try { 33 | c = (char) br.read(); 34 | System.out.println("你输入的字符是:" + c); 35 | } catch (IOException e) { 36 | System.out.println("获取输入内容失败"); 37 | } 38 | } while (c != 'q'); 39 | } 40 | 41 | // 读取输入的字符串 42 | public static void BRReadLine() { 43 | // 使用 System.in 创建 BufferedReader 44 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 45 | String str = ""; 46 | System.out.println("Enter lines of text."); 47 | System.out.println("Enter 'end' to quit."); 48 | do { 49 | try { 50 | str = br.readLine(); 51 | } catch (IOException e) { 52 | // TODO Auto-generated catch block 53 | e.printStackTrace(); 54 | } 55 | System.out.println("你输入的是:" + str); 56 | } while (!str.equals("end")); 57 | } 58 | 59 | // 控制台输出 60 | public static void Write() { 61 | char b; 62 | b = 'A'; 63 | System.out.write(b); 64 | System.out.write('\n'); 65 | System.out.println("第二种输出方法"); 66 | } 67 | 68 | // 目录操作 69 | // mkdir()方法创建一个文件夹,成功则返回true,失败则返回false。失败表明File对象指定的路径已经存在,或者由于整个路径还不存在,该文件夹不能被创建。 70 | // mkdirs()方法创建一个文件夹和它的所有父文件夹。 71 | public static void mkdirs() { 72 | String dirname = "mkdirs/test"; 73 | File d = new File(dirname); 74 | // 现在创建目录 75 | d.mkdirs(); 76 | System.out.println("成功"); 77 | } 78 | 79 | // 文件操作 80 | public static void fileStream() { 81 | try { 82 | File f = new File("mkdirs/test/filetest.txt"); 83 | FileOutputStream fop = new FileOutputStream(f); 84 | // 构建FileOutputStream对象,文件不存在会自动新建 85 | 86 | OutputStreamWriter writer = new OutputStreamWriter(fop, "gbk"); 87 | // 构建OutputStreamWriter对象,参数可以指定编码,默认为操作系统默认编码,windows上是gbk 88 | 89 | writer.append("中文输入"); 90 | // 写入到缓冲区 91 | 92 | writer.append("\r\n"); 93 | // 换行 94 | 95 | writer.append("English"); 96 | // 刷新缓存冲,写入到文件,如果下面已经没有写入的内容了,直接close也会写入 97 | 98 | writer.close(); 99 | // 关闭写入流,同时会把缓冲区内容写入文件,所以上面的注释掉 100 | 101 | fop.close(); 102 | // 关闭输出流,释放系统资源 103 | 104 | FileInputStream fip = new FileInputStream(f); 105 | // 构建FileInputStream对象 106 | 107 | InputStreamReader reader = new InputStreamReader(fip, "UTF-8"); 108 | // 构建InputStreamReader对象,编码与写入相同 109 | 110 | StringBuffer sb = new StringBuffer(); 111 | while (reader.ready()) { 112 | sb.append((char) reader.read()); 113 | // 转成char加到StringBuffer对象中 114 | } 115 | System.out.println(sb.toString()); 116 | reader.close(); 117 | // 关闭读取流 118 | 119 | fip.close(); 120 | // 关闭输入流,释放系统资源 121 | } catch (Exception e) { 122 | } 123 | } 124 | 125 | //读取目录下的所有子目录和文件 126 | public static void dirList(String dirName) { 127 | File f1 = new File(dirName); 128 | if (f1.isDirectory()) { 129 | System.out.println("目录:" + dirName); 130 | String s[] = f1.list(); 131 | for (int i = 0; i < s.length; i++) { 132 | dirList(dirName + "/" + s[i]); 133 | } 134 | } else { 135 | System.out.println("文件:" + dirName); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/FinalDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | 4 | //根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。 5 | // 6 | //【1】final类不能被继承,没有子类,final类中的方法默认是final的。 7 | // 8 | //【2】final方法不能被子类的方法覆盖,但可以被继承。 9 | // 10 | //【3】final成员变量表示常量,只能被赋值一次,赋值后值不再改变。 11 | // 12 | //【4】final不能用于修饰构造方法。 13 | // 14 | //【5】注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。 15 | public class FinalDemo { 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/InnerClassDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //内部类 4 | //http://www.cnblogs.com/wangzhongqiu/p/6574019.html 5 | public class InnerClassDemo { 6 | public static void main(String[] args) { 7 | // 常规内部类 8 | // 内部类中的变量访问形式 9 | Out1.In in = new Out1().new In(); 10 | in.print(); 11 | 12 | // 静态内部类 13 | Out2.In in2 = new Out2.In(); 14 | 15 | // 私有内部类 16 | Out3 out3 = new Out3(); 17 | out3.outPrint(); 18 | 19 | // 局部内部类 20 | Out4 out4 = new Out4(); 21 | out4.Print(5); 22 | 23 | // 匿名内部类 24 | out5 out5 = new out5(); 25 | out5.print(); 26 | 27 | Object o = new Object(); 28 | } 29 | } 30 | 31 | // 常规内部类 32 | // 内部类中的变量访问形式 33 | class Out1 { 34 | private int age = 12; 35 | 36 | // 内部类 37 | class In { 38 | private int age = 13; 39 | 40 | public void print() { 41 | int age = 14; 42 | System.out.println("局部变量:" + age); 43 | System.out.println("内部类变量:" + this.age); 44 | System.out.println("外部类变量:" + Out1.this.age); 45 | } 46 | } 47 | } 48 | 49 | // 静态内部类 50 | class Out2 { 51 | private static int age = 12; 52 | private int normalage = 13; 53 | 54 | static class In { 55 | public void print() { 56 | System.out.println(age); 57 | // 静态内部类不能访问外部类的非静态成员变量 58 | // System.out.println(normalage); 59 | } 60 | } 61 | } 62 | 63 | // 私有内部类 64 | class Out3 { 65 | private int age = 12; 66 | 67 | private class In { 68 | public void print() { 69 | System.out.println(age); 70 | } 71 | } 72 | 73 | public void outPrint() { 74 | new In().print(); 75 | } 76 | } 77 | 78 | // 局部内部类 79 | class Out4 { 80 | private int age = 12; 81 | 82 | public void Print(final int x) { 83 | class In { 84 | public void inPrint() { 85 | System.out.println(x); 86 | System.out.println(age); 87 | } 88 | } 89 | new In().inPrint(); 90 | } 91 | } 92 | 93 | // 匿名内部类 94 | class out5 { 95 | public void print() { 96 | new Thread(new Runnable() { 97 | public void run() { 98 | for (int i = 1; i <= 5; i++) { 99 | System.out.print(i + " "); 100 | } 101 | } 102 | }).start(); 103 | } 104 | } -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/MathRandomDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | import java.util.Random; 4 | 5 | //随机数。Math.random() -- 返回0和1之间的伪随机数 可能为0,但总是小于1,[0,1) 6 | public class MathRandomDemo { 7 | public static void main(String[] args) { 8 | intAndChar(); 9 | for (int i = 0; i < 100; i++) { 10 | System.out.println(Math.random()); 11 | } 12 | for (int i = 0; i < 10; i++) { 13 | sixRandomStr(); 14 | } 15 | } 16 | 17 | // int和char对应关系 18 | public static void intAndChar() { 19 | for (int i = 1; i < 257; i++) { 20 | System.out.println(i + "对应:" + (char) i); 21 | } 22 | } 23 | 24 | // 生成一个6位的随机字符串 25 | public static void sixRandomStr() { 26 | String result = ""; 27 | for (int i = 0; i < 6; i++) { 28 | // 生成97-122的int型的整型 29 | int intValue = (int) (Math.random() * 25 + 97); 30 | // 将intValue强制转化成char类型后接到result后面 31 | result = result + (char) intValue; 32 | } 33 | // 输出字符串 34 | System.out.println(result); 35 | } 36 | 37 | public static int getRadom(int i) { 38 | Random r = new Random(); 39 | return r.nextInt(i); 40 | } 41 | 42 | //获取长度为n的随机数组,局限性:数组里会有重复 43 | public static int[] getRandomIntArrayWithRepeat(int n) { 44 | Random r = new Random(); 45 | int[] a = new int[n]; 46 | for (int i = 0; i < n; i++) { 47 | a[i] = r.nextInt(n); 48 | } 49 | return a; 50 | } 51 | 52 | /** 53 | * 随机指定范围内N个不重复的数 54 | * 在初始化的无重复待选数组中随机产生一个数放入结果中, 55 | * 将待选数组被随机到的数,用待选数组(len-1)下标对应的数替换 56 | * 然后从len-2里随机产生下一个随机数,如此类推 57 | * 58 | * @param max 指定范围最大值 59 | * @param min 指定范围最小值 60 | * @param n 随机数个数 61 | * @return int[] 随机数结果集 62 | */ 63 | public static int[] getRandomIntArrayWithoutRepeat(int min, int max, int n) { 64 | int len = max - min + 1; 65 | 66 | if (max < min || n > len) { 67 | return null; 68 | } 69 | 70 | //初始化给定范围的待选数组 71 | int[] source = new int[len]; 72 | for (int i = min; i < min + len; i++) { 73 | source[i - min] = i; 74 | } 75 | 76 | int[] result = new int[n]; 77 | Random rd = new Random(); 78 | int index = 0; 79 | for (int i = 0; i < result.length; i++) { 80 | //待选数组0到(len-2)随机一个下标 81 | index = Math.abs(rd.nextInt() % len--); 82 | //将随机到的数放入结果集 83 | result[i] = source[index]; 84 | //将待选数组中被随机到的数,用待选数组(len-1)下标对应的数替换 85 | source[index] = source[len]; 86 | } 87 | return result; 88 | } 89 | 90 | public static int[] getIntArrayAsc(int n) { 91 | int[] a = new int[n]; 92 | for (int i = 0; i < n; i++) { 93 | a[i] = i; 94 | } 95 | return a; 96 | } 97 | 98 | public static int[] getIntArrayDesc(int n) { 99 | int[] a = new int[n]; 100 | for (int i = 0; i < n; i++) { 101 | a[i] = n - i - 1; 102 | } 103 | return a; 104 | } 105 | 106 | public static int[] getIntArrayAllRepeat(int n, int repeat) { 107 | int[] a = new int[n]; 108 | for (int i = 0; i < n; i++) { 109 | a[i] = repeat; 110 | } 111 | return a; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/NetDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //网络编程 socket,tcp/ip,url 4 | //http://www.runoob.com/java/java-networking.html 5 | //http://www.runoob.com/java/java-url-processing.html 6 | public class NetDemo { 7 | public static void main(String[] args) { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/NumberDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //Number类相关 4 | public class NumberDemo { 5 | /* 6 | * 在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情形。为了解决这个问题,Java 语言为每一个内置数据类型提供了对应的包装类。 7 | * 所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。 8 | */ 9 | 10 | /* 11 | * Number方法 compareTo() equals() 等等 12 | */ 13 | public static void main(String[] args) { 14 | Integer aInteger = 1; 15 | Integer bInteger = 1; 16 | Integer aInteger2 = new Integer(1); 17 | Integer bInteger2 = new Integer(1); 18 | 19 | System.out.println(aInteger == bInteger); 20 | System.out.println(aInteger == aInteger2); 21 | System.out.println(aInteger2 == bInteger2); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/OperatorDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //运算符操作 4 | public class OperatorDemo { 5 | public static void main(String[] args) { 6 | self(); 7 | three(); 8 | instanceOf(); 9 | } 10 | 11 | // a++,a--。自增自减运算符 12 | // 1、前缀自增自减法(++a,--a): 先进行自增或者自减运算,再进行表达式运算。 13 | // 2、后缀自增自减法(a++,a--): 先进行表达式运算,再进行自增或者自减运算 实例: 14 | public static void self() { 15 | int a = 5;// 定义一个变量; 16 | int b = 5; 17 | int x = 2 * ++a; 18 | int y = 2 * b++; 19 | System.out.println("自增运算符前缀运算后a=" + a + ",x=" + x); 20 | System.out.println("自增运算符后缀运算后b=" + b + ",y=" + y); 21 | } 22 | 23 | // 条件运算符(三元运算符)(?:) 24 | public static void three() { 25 | int a, b; 26 | a = 10; 27 | b = (a == 1) ? 20 : 30; 28 | System.out.println("Value of b is : " + b); 29 | b = (a == 10) ? 20 : 30; 30 | System.out.println("Value of b is : " + b); 31 | } 32 | 33 | // instanceof运算符.判断是否为一个类的实例 34 | public static void instanceOf() { 35 | String name = "James"; 36 | boolean result = name instanceof String; 37 | System.out.println(result); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/Reflection.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | //反射就是在运行状态把 Java 类中的各种成分映射成相应相应的 Java 类,可以动态得获取所有的属性以及动态调用任意一个方法。 7 | //1).一段java代码在程序的运行期间会经历三个阶段:source-->class-->runtime 8 | //2).Class对象 9 | // 在java中用一个Class对象来表示一个java类的class阶段 10 | // Class对象封装了一个java类定义的成员变量、成员方法、构造方法、包名、类名等。 11 | public class Reflection { 12 | public static void main(String[] args) 13 | throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, 14 | SecurityException, IllegalArgumentException, InvocationTargetException { 15 | // 通过类名来构造一个类的实例 16 | Class cls_str = Class.forName("java.lang.String"); 17 | // 上面这句很眼熟,因为使用过 JDBC 访问数据库的人都用过 J 18 | Object str = cls_str.newInstance(); 19 | // 相当于 String str = new String(); 20 | 21 | // 通过方法名来调用一个方法 22 | String methodName = "length"; 23 | Method m = cls_str.getMethod(methodName, null); 24 | System.out.println("length is " + m.invoke(str, null)); 25 | // 相当于 System.out.println(str.length()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/RegexDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | //正则相关 7 | //http://www.runoob.com/java/java-regular-expressions.html 8 | public class RegexDemo { 9 | public static void main(String[] args) { 10 | // match(); 11 | replace(); 12 | } 13 | 14 | public static void match() { 15 | // 按指定模式在字符串查找 16 | String line = "This order was placed for QT3000! OK?"; 17 | String pattern = "(\\D*)(\\d+)(.*)"; 18 | 19 | // 创建 Pattern 对象 20 | Pattern r = Pattern.compile(pattern); 21 | 22 | // 现在创建 matcher 对象 23 | Matcher m = r.matcher(line); 24 | if (m.groupCount() > 0) { 25 | System.out.println(m.groupCount()); 26 | for (int i = 0; i < m.groupCount(); i++) { 27 | System.out.println("Found value: " + m.group(i)); 28 | } 29 | } else { 30 | System.out.println("NO MATCH"); 31 | } 32 | } 33 | 34 | public static void replace() { 35 | String REGEX = "dog"; 36 | String INPUT = "The dog says meow. " + "All dogs say meow."; 37 | 38 | // 全部替换 39 | System.out.println(Pattern.compile(REGEX).matcher(INPUT).replaceAll("cat")); 40 | 41 | // 替换第一个 42 | System.out.println(Pattern.compile(REGEX).matcher(INPUT).replaceFirst("cat")); 43 | 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/SendMailDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //发邮件 send mail 4 | //http://www.runoob.com/java/java-sending-email.html 5 | public class SendMailDemo { 6 | public static void main(String[] args) { 7 | 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/SerializeDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //序列化 Serialize 4 | //http://www.runoob.com/java/java-serialization.html 5 | public class SerializeDemo { 6 | public static void main(String[] args) { 7 | 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/StringDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //String相关 4 | public class StringDemo { 5 | /* 6 | * String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 7 | * 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 8 | * String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。 9 | */ 10 | 11 | // StringBuffer 字符串变量(线程安全) 12 | // StringBuilder 字符串变量(非线程安全) 13 | // 大部分情况下 StringBuilder>StringBuffer>String 14 | 15 | public static void main(String[] args) { 16 | stringBuilderDemo(); 17 | } 18 | 19 | // StringBuilder 20 | public static void stringBuilderDemo() { 21 | // 创建实例化对象 22 | StringBuilder sb = new StringBuilder("Hello World!"); 23 | StringBuffer stringBuffer = new StringBuffer(); 24 | // apend用法 25 | sb.append("aaaa"); 26 | System.out.println(sb); 27 | 28 | // insert用法.在序号4的前面插入 29 | sb.insert(4, "23456"); 30 | System.out.println(sb); 31 | 32 | // StringBuffer delete(start,end):删除缓冲区中的数据,包含Start,不包含end 33 | // StringBuffer deleteCharAt(index);删除缓冲区指定位置的数据 34 | sb.delete(1, 3); 35 | System.out.println(sb.toString()); 36 | sb.deleteCharAt(0); 37 | System.out.println(sb.toString()); 38 | // sb.delete(0,sb.length()):清空缓冲区 39 | 40 | // 获取 41 | char c = sb.charAt(2); 42 | System.out.println(c); 43 | int index = sb.indexOf("a"); 44 | System.out.println(index); 45 | 46 | // 修改,也可以理解为替换 47 | sb.replace(1, 3, "java"); 48 | System.out.println(sb.toString()); 49 | sb.setCharAt(2, 'm'); 50 | System.out.println(sb.toString()); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/SwitchDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | //Switch用法 4 | /* 5 | * switch(A),括号中A的取值只能是整型或者可以转换为整型的数值类型,比如byte、short、int、char、还有枚举; 6 | 需要强调的是:long和String类型是不能作用在switch语句上的。 7 | * case B:C;case是常量表达式,也就是说B的取值只能是常量(需要定义一个final型的常量) 8 | 或者int、byte、short、char(比如1、2、3、200000000000(注意了这是整型)), 9 | 而case后的常量值与switch后的表达式相对应。 case后的语句可以不用大括号,就是C不需要用大括号包裹着; 10 | * default就是如果没有符合的case就执行它,default并不是必须的. 11 | * 一旦case匹配,就会顺序执行后面的程序代码,而不管后面的case是否匹配,直到遇见break,利用这一特性可以让好几个case执行统一语句. 12 | * switch中可以使用字串了。这个新特性是在编译器这个层次上实现的 13 | */ 14 | public class SwitchDemo { 15 | public static void main(String[] args) { 16 | String s = "test"; 17 | switch (s) { 18 | case "test": 19 | System.out.println("test"); 20 | break; 21 | case "a": 22 | System.out.println("a"); 23 | break; 24 | case "test1": 25 | System.out.println("test1"); 26 | break; 27 | default: 28 | System.out.println("break"); 29 | break; 30 | } 31 | 32 | final int i = 3; 33 | switch (i) { 34 | case '3': 35 | System.out.println(1); 36 | break; 37 | case 2: 38 | System.out.println(2); 39 | break; 40 | case 223: 41 | System.out.println(128); 42 | break; 43 | default: 44 | System.out.println("default"); 45 | break; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/ThrowableDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base; 2 | 3 | import java.nio.BufferOverflowException; 4 | 5 | //异常 6 | //http://www.runoob.com/java/java-exceptions.html 7 | public class ThrowableDemo extends Throwable { 8 | /* Throwable包含了错误(Error)和异常(Exception两类) 9 | Exception又包含了运行时异常(RuntimeException, 又叫非检查异常)和非运行时异常(又叫检查异常) 10 | (1) Error是程序无法处理了, 这些异常发生时,java虚拟机一般会终止线程. 11 | OutOfMemoryError,内存溢出 12 | StackOverflowError,堆栈溢出 13 | (2) 运行时异常都是RuntimeException类及其子类, 14 | 是在程序运行的时候可能会发生的, 所以程序可以捕捉, 也可以不捕捉. 这些错误一般是由程序的逻辑错误引起的, 程序应该从逻辑角度去尽量避免 NullPointerException 空指针异常 15 | IndexOutOfBoundsException 数组越界异常 16 | ClassCastException 类转换异常 17 | ArrayStoreException 数组存储异常 18 | nio.BufferOverflowException 缓冲区溢出 19 | (3) 检查异常是运行时异常以外的异常, 也是Exception及其子类, 这些异常从程序的角度来说是必须经过捕捉检查处理的, 否则不能通过编译. 20 | IOException 21 | SQLException 22 | ClassNotFoundException,继承自ReflectiveOperationException 23 | FileNotFoundException,继承自ReflectiveOperationException 24 | ReflectiveOperationException 25 | InterruptedException 26 | 当某个线程处于长时间的等待、休眠或其他暂停状态,而此时其他的线程通过Thread的interrupt方法终止该线程时抛出该异常。 27 | (4) throw语句用在方法体内,表示抛出异常,由方法体内的语句处理。 28 | throws语句用在方法声明后面,表示再抛出异常,由该方法的调用者来处理。*/ 29 | public static void main(String[] args) { 30 | // OutOfMemoryError 31 | // BufferOverflowException 32 | // StackOverflowError 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/dynamicplanning/BestLoading.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.dynamicplanning; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by wangzhongqiu on 2017/8/6. 8 | * 最优装载问题。有一批集装箱要装上一艘载重量为c的轮船。其中集装箱i的重量为Wi。要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。 9 | * 关键字:装载体积不受限制,尽可能多的集装箱装上轮船 10 | * 解决方案:贪心算法 11 | */ 12 | 13 | public class BestLoading { 14 | public float loading(float maxWeight, float[] weights, List x) { 15 | int n = weights.length; 16 | Element[] d = new Element[n]; 17 | for (int i = 0; i < n; i++) { 18 | d[i] = new Element(weights[i], i); 19 | } 20 | java.util.Arrays.sort(d); 21 | float op = 0; 22 | int xNum = 0; 23 | for (int i = 0; i < n && d[i].weight <= maxWeight; i++) { 24 | op += d[i].weight; 25 | maxWeight -= d[i].weight; 26 | x.add(d[i].index); 27 | } 28 | return op; 29 | } 30 | 31 | static class Element implements Comparable { 32 | float weight; 33 | int index; 34 | 35 | public Element(float w, int i) { 36 | weight = w; 37 | index = i; 38 | } 39 | 40 | @Override 41 | public int compareTo(Object x) {//按每个重量从小到大排列 42 | float xx = ((Element) x).weight; 43 | if (this.weight < xx) return -1; 44 | if (this.weight == xx) return 0; 45 | return 1; 46 | } 47 | } 48 | 49 | public static void main(String[] args) { 50 | float w[] = {20, 10, 26, 15};//下标从0开始 51 | float c = 70; 52 | List x = new ArrayList<>(); 53 | BestLoading be = new BestLoading(); 54 | System.out.println("最优得到装载重量为:" + be.loading(c, w, x)); 55 | System.out.println("被装载的集装箱序号为(下标从0开始):"); 56 | for (int i = 0; i < x.size(); i++) { 57 | System.out.print(x.get(i) + ","); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/dynamicplanning/knapsack.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.dynamicplanning; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/30. 5 | * 01背包问题。 6 | * F[i,v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。状态转移方程:F[i,v]=max{F[i−1,v],F[i−1,v−Ci]+Wi} 7 | */ 8 | public class Knapsack { 9 | public static void main(String[] args) { 10 | int[] weight = {3, 5, 2, 6, 4}; //物品重量 11 | int[] val = {4, 4, 3, 5, 3}; //物品价值 12 | int m = 12; //背包容量 13 | // knapsack01ByTwoDimensionalArray(m, weight, val); 14 | knapsack01(m, weight, val, true); 15 | } 16 | 17 | /** 18 | * 01背包。每个物品最多放一个。恰好装满背包 19 | * 20 | * @param m 背包容量 21 | * @param weight 物品重量 22 | * @param val 物品价值 23 | * 主要思想,利用动态规划来解决。每次遍历到的第i个物品,根据w[i]和v[i]来确定是否需要将该物品放入背包中。 24 | * 即对于给定的n个物品,设v[i]、w[i]分别为第i个物品的价值和重量,C为背包的容量。 25 | * 再令v[i][j]表示在前i个物品中能够装入容量为j的背包中的最大价值。则我们有下面的结果: 26 | * (1)v[i][0]=v[0][j]=0; 27 | * (2)v[i][j]=v[i-1][j] 当w[i]>j 28 | * (3)v[i][j]=max{v[i-1][j],v[i-1][j-w[i]]+v[i]} 当j>=w[i] 29 | */ 30 | public static void knapsack01ByTwoDimensionalArray(int m, int[] weight, int[] val) { 31 | int n = val.length; //物品个数 32 | int[][] f = new int[n + 1][m + 1]; //f[i][j]表示前i个物品能装入容量为j的背包中的最大价值 33 | int[][] path = new int[n + 1][m + 1];//标记 34 | //初始化第一列和第一行 35 | for (int i = 0; i < f.length; i++) { 36 | f[i][0] = 0; 37 | } 38 | for (int i = 0; i < f[0].length; i++) { 39 | f[0][i] = 0; 40 | } 41 | //通过公式迭代计算 42 | for (int i = 1; i < f.length; i++) { 43 | for (int j = 1; j < f[0].length; j++) { 44 | if (weight[i - 1] > j) 45 | f[i][j] = f[i - 1][j]; 46 | else { 47 | if (f[i - 1][j] < f[i - 1][j - weight[i - 1]] + val[i - 1]) { 48 | f[i][j] = f[i - 1][j - weight[i - 1]] + val[i - 1]; 49 | path[i][j] = 1; 50 | } else { 51 | f[i][j] = f[i - 1][j]; 52 | } 53 | } 54 | } 55 | } 56 | for (int i = 1; i < f.length; i++) { 57 | for (int j = 1; j < f[0].length; j++) { 58 | System.out.print(f[i][j] + " "); 59 | } 60 | System.out.println(); 61 | } 62 | int i = f.length - 1; 63 | int j = f[0].length - 1; 64 | while (i > 0 && j > 0) { 65 | if (path[i][j] == 1) { 66 | System.out.println("第" + i + "个物品装入 "); 67 | j -= weight[i - 1]; 68 | } 69 | i--; 70 | } 71 | System.out.print("最大价值:" + f[f.length - 1][f[0].length - 1]); 72 | } 73 | 74 | /** 75 | * 一维数组实现,更节省空间 76 | * 77 | * @param m 背包容量 78 | * @param weight 物品重量 79 | * @param val 物品价值 80 | * @param needFull 是否需要装满 81 | */ 82 | public static void knapsack01(int m, int[] weight, int[] val, boolean needFull) { 83 | int n = val.length; //物品个数 84 | int[] f = new int[m + 1];//f[i]代表背包容量为i时的最大价值。 85 | int[] path = new int[m + 1];//标记 86 | //初始化 87 | if (needFull) { 88 | for (int i = 1; i < f.length; i++) { //必装满则f[0]=0,f[1...m]都初始化为无穷小 89 | f[i] = Integer.MIN_VALUE; 90 | } 91 | } else { 92 | for (int i = 0; i < f.length; i++) { //不必装满则初始化为0 93 | f[i] = 0; 94 | } 95 | } 96 | for (int i = 0; i < n; i++) { 97 | for (int j = f.length - 1; j >= weight[i]; j--) { 98 | if (f[j] < f[j - weight[i]] + val[i]) { 99 | f[j] = f[j - weight[i]] + val[i]; 100 | } 101 | // f[j] = Math.max(f[j], f[j - weight[i]] + val[i]); 102 | } 103 | for (int k = 0; k < f.length; k++) { 104 | System.out.print(f[k] + " ,"); 105 | } 106 | System.out.println(); 107 | } 108 | System.out.println(); 109 | System.out.println("最大价值为" + f[f.length - 1]); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/dynamicplanning/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by wangzhongqiu on 2017/8/30. 3 | * 动态规划问题 4 | * 贪心算法 5 | * 动态规划 6 | */ 7 | package zhongqiu.common.base.algorithm.dynamicplanning; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | /** 5 | * @author Administrator 6 | * 数据结构和算法 7 | * (1)二叉树,5种形态;满二叉树;完全二叉树;哈夫曼树(最优二叉树), 8 | * 最短带权路径长度;二叉排序树;平衡二叉树; 9 | * 红黑树(自平衡二叉查找树): 10 | * put,先寻找插入点,生成二叉查找树,在进行平衡处理,左旋,右旋,着色操作。 11 | * delete,找到一个替代子节点C来替代P,然后直接删除C,最后调整这棵红黑树 12 | * 二叉树的遍历:先序遍历,中序遍历,后序遍历,层次遍历; 13 | * (2)排序算法:插入排序,冒泡排序,堆排序,归并排序,快速排序 14 | * (3)查找算法:二分查找 15 | * (4)动态规划,背包问题 16 | */ 17 | package zhongqiu.common.base.algorithm; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/CrazyQueue.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/6. 7 | * 题目:疯狂队列 8 | * 出处:网易2018校招 9 | * 来源:牛客网 10 | * 测试结果:90%测试用例通过 11 | */ 12 | public class CrazyQueue { 13 | public static void main(String[] args) { 14 | Scanner sc = new Scanner(System.in); 15 | int total = sc.nextInt(); 16 | int[] arr = new int[total]; 17 | for (int i = 0; i < total; i++) { 18 | arr[i] = sc.nextInt(); 19 | } 20 | insertSort(arr, 0, arr.length - 1); 21 | int[] newArray = create(arr); 22 | int num = calculate(newArray); 23 | System.out.println(num); 24 | } 25 | 26 | public static void insertSort(int[] arr, int low, int high) { 27 | int i, j; 28 | int n = arr.length; 29 | int target; 30 | //假定第一个元素被放到了正确的位置上 31 | //这样,仅需遍历1 - n-1 32 | for (i = low + 1; i < high + 1; i++) { 33 | j = i; 34 | target = arr[j]; 35 | while (j > 0 && target < arr[j - 1]) { 36 | arr[j] = arr[j - 1]; 37 | j--; 38 | } 39 | arr[j] = target; 40 | } 41 | } 42 | 43 | public static int[] create(int[] arr) { 44 | int[] newArray = new int[arr.length]; 45 | int i = 0; 46 | int j = arr.length - 1; 47 | int newI = 0; 48 | int m = (i + j) / 2; 49 | newArray[m] = arr[j]; 50 | j--; 51 | int num = 0; 52 | while (i <= j) { 53 | switch (num) { 54 | case 0: 55 | newArray[m + newI + 1] = arr[i]; 56 | i++; 57 | num++; 58 | break; 59 | case 1: 60 | newArray[m - newI - 1] = arr[i]; 61 | i++; 62 | newI = newI + 1; 63 | num++; 64 | break; 65 | case 2: 66 | newArray[m + newI + 1] = arr[j]; 67 | num++; 68 | j--; 69 | break; 70 | case 3: 71 | newArray[m - newI - 1] = arr[j]; 72 | j--; 73 | newI = newI + 1; 74 | num++; 75 | break; 76 | } 77 | if (num == 4) { 78 | num = 0; 79 | } 80 | } 81 | return newArray; 82 | } 83 | 84 | public static int calculate(int[] arr) { 85 | int num = 0; 86 | for (int i = 0; i < arr.length - 1; i++) { 87 | if (arr[i + 1] - arr[i] >= 0) { 88 | num = num + arr[i + 1] - arr[i]; 89 | } else { 90 | num = num + arr[i] - arr[i + 1]; 91 | } 92 | } 93 | return num; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/ErrorRecords.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/16. 5 | *

6 | *  * 正如大家之前所说,这个题主要是考细节。所以我只说说代码的细节: 7 | *  *   1. 读到文件路径,先用substring截取文件名。 8 | *  *   2. 用Entry对象保存单个记录和出现次数。 9 | *  *   3. 用Map来区分是否为新纪录,这要求Entry重新equals和hashCode。 10 | *  *   4. 真正使用的是LinkedHashMap,使得遍历key时可以按照插入顺序遍历,满足了题目要求。 11 | *  *   5. Arrays.sort对引用类型采用插入排序+归并排序,保证了排序稳定性,满足了题目要求。 12 | *  *   6. Entry实现了Comparable接口,其实更好是写一个Comparator,因为是刷题无所谓了。 13 | *  *   7. 对文件名长度的判定在Entry的toString中,这样写不好,因为是刷题无所谓了。 14 | **/ 15 | 16 | import java.util.Arrays; 17 | import java.util.HashMap; 18 | import java.util.LinkedHashMap; 19 | import java.util.Scanner; 20 | 21 | public class ErrorRecords { 22 | public static void main(String[] args) { 23 | Scanner scan = new Scanner(System.in); 24 | HashMap records = new LinkedHashMap(); 25 | while (scan.hasNext()) { 26 | String name = scan.next(); 27 | int lines = scan.nextInt(); 28 | int index = name.lastIndexOf('\\'); 29 | // 截取文件名 30 | if (index != -1) 31 | name = name.substring(index + 1); 32 | // 生成Entry 33 | Entry entry = new Entry(name, lines); 34 | if (records.containsKey(entry)) { 35 | // 合并 36 | Entry old = records.get(entry); 37 | old.count++; 38 | } else { 39 | // 新的 40 | records.put(entry, entry); 41 | } 42 | } 43 | scan.close(); // 获得结果 44 | Entry[] result = new Entry[records.size()]; 45 | result = records.keySet().toArray(result); 46 | Arrays.sort(result); 47 | // 输出结果 48 | int size = Math.min(8, result.length); 49 | for (int i = 0; i < size; i++) { 50 | System.out.println(result[i]); 51 | } 52 | } 53 | 54 | private static class Entry implements Comparable { 55 | public String name; 56 | public int lines; 57 | public int count; 58 | 59 | public Entry(String n, int l) { 60 | this.name = n; 61 | this.lines = l; 62 | this.count = 1; 63 | } 64 | 65 | @Override 66 | public int compareTo(Entry e) { 67 | if (this.count < e.count) 68 | return 1; 69 | else if (this.count == e.count) 70 | return 0; 71 | else 72 | return -1; 73 | } 74 | 75 | @Override 76 | public int hashCode() { 77 | return name.hashCode() + lines; 78 | } 79 | 80 | @Override 81 | public boolean equals(Object obj) { 82 | if (obj == this) 83 | return true; 84 | if (obj instanceof Entry) { 85 | Entry e = (Entry) obj; 86 | if (e.name.equals(this.name) && e.lines == this.lines) 87 | return true; 88 | } 89 | return false; 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | if (name.length() <= 16) 95 | return name + " " + lines + " " + count; 96 | else 97 | return name.substring(name.length() - 16, name.length()) + " " + lines + " " + count; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/FindFirstOnceOccurCharactar.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/23. 5 | * 360题:寻找字符串中第一个只出现一次的字符 6 | * 正在挑战一个CrackMe的你,把需要填写的前面几位密码都正确猜出了,可是这最后一位密码,好像藏得有点深。CrackMe的作者还挑衅般的在里面藏了个.tar.gz文件,解压缩出来,里面写道 你要的最后一个字符就在下面这个字符串里,这个字符是下面整个字符串中第一个只出现一次的字符。(比如,串是abaccdeff,那么正确字符就是b了) 然而下面给出来的字符串好像太长太长了,单靠人力完全无法找出来。 于是,你需要写一个程序代劳了。输入文件体积较大,请使用一些快速的输入输出手段,不推荐使用cin/cout,对Java并不推荐使用Scanner直接读写。 7 | *

8 | * 输入描述: 9 | * 第一行,一个正整数T(T≤20) ,表示输入数据组数。 10 | * 之后T行,每行一个字符串S。( 1≤S 的长度≤1000000 ,保证字符串中出现的字符的ASCII码在[0x21,0x7F)范围内,即均为可显示的非空白符,同时保证一定有解) 11 | * 输出描述: 12 | * 一共T 行,每行一个字符C ,表示所给的相应字符串中第一个只出现一次的字符。 13 | * 示例1 14 | * 输入 15 | * 2 16 | * abaccdeff 17 | * testonline 18 | * 输出 19 | * b 20 | * s 21 | */ 22 | 23 | import java.io.BufferedReader; 24 | import java.io.IOException; 25 | import java.io.InputStreamReader; 26 | import java.util.ArrayList; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | 30 | public class FindFirstOnceOccurCharactar { 31 | public static void main(String[] args) { 32 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); 33 | int total = 0; 34 | List list = new ArrayList<>(); 35 | try { 36 | total = Integer.parseInt(bufferedReader.readLine()); 37 | for (int i = 0; i < total; i++) { 38 | list.add(bufferedReader.readLine()); 39 | } 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | HashMap map = new HashMap<>(); 44 | for (int i = 0; i < list.size(); i++) { 45 | String temp = list.get(i); 46 | for (int j = 0; j < temp.length(); j++) { 47 | if (map.containsKey(temp.charAt(j))) { 48 | map.put(temp.charAt(j), map.get(temp.charAt(j)) + 1); 49 | } else { 50 | map.put(temp.charAt(j), 1); 51 | } 52 | } 53 | for (int j = 0; j < temp.length(); j++) { 54 | if (map.get(temp.charAt(j)) == 1) { 55 | System.out.println(temp.charAt(j)); 56 | break; 57 | } 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/FindSubString.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/23. 7 | * 360题目,疯狂大脑 8 | *

9 | * 小B乘火车和朋友们一起在N市到M市之间旅行。她在路途中时睡时醒。当她醒来观看窗外的风景时,注意到每个火车站都有一种特别颜色的旗帜,但是她看到的旗帜仅仅是经过的一小部分。小B在乘车过程中有两次清醒的时间,她到达旅程终点时处于睡梦中。出站时,她和朋友们谈论着一路的见闻,朋友们觉得很有意思,他们把N到和M之间经过车站的旗帜颜色依次列出来,然后告诉你小B记得的旗帜颜色序列,让你判断小B究竟是从N和M之间哪些方向才能看到所说颜色的旗帜,还是根本就不可能看到?颜色用字母代表,相同的字母代表相同的颜色,不同的字母则表示不同的颜色。 10 | *

11 | *

12 | * 输入中有多组测试数据,每组测试数据包含三行,第一行为一个由小写拉丁字母构成的非空字符串,长度不超过10^5,表示N到M之间车站的颜色。火车从M向N运行时, 经过的车站相同,只是方向相反。第二行为小B在第一次睡醒时看到的颜色序列,第三行为小B在第二次睡醒时看到的颜色序列。两个序列都是小写的拉丁字母构成的字符串,长度不超过100个字母。每个序列的颜色顺序排列按小B看到的时间顺序排列。 13 | *

14 | * 对每组测试数据,在单独的行中输出小B的旅行方向。 15 | * forward - 由N到M方向; 16 | * backward -由M到N方向 17 | * both - 两种方向都有可能; 18 | * invalid - 不可能看到这样的颜色序列; 19 | *

20 | * 示例1 21 | * 输入 22 | * atob 23 | * a 24 | * b 25 | * aaacaaa 26 | * aca 27 | * aa 28 | * 输出 29 | * forward 30 | * both 31 | */ 32 | public class FindSubString { 33 | public static void main(String[] args) { 34 | Scanner scan = new Scanner(System.in); 35 | String nm = scan.next(); 36 | String one = scan.next(); 37 | String two = scan.next(); 38 | int flag = -1; 39 | int oneIndex = -1; 40 | int twoIndex = -1; 41 | 42 | oneIndex = nm.indexOf(one); 43 | twoIndex = -1; 44 | if (oneIndex != -1) { 45 | twoIndex = nm.indexOf(two, oneIndex + one.length()); 46 | if (twoIndex != -1) { 47 | flag = 0; 48 | } 49 | } 50 | 51 | nm = new StringBuilder(nm).reverse().toString(); 52 | 53 | oneIndex = nm.indexOf(one); 54 | if (oneIndex != -1) { 55 | twoIndex = nm.indexOf(two, oneIndex + one.length()); 56 | if (twoIndex != -1) { 57 | if (flag == -1) { 58 | flag = 1; 59 | } else if (flag == 0) { 60 | flag = 2; 61 | } 62 | } 63 | } 64 | 65 | switch (flag) { 66 | case 0: 67 | System.out.println("forward"); 68 | break; 69 | case 1: 70 | System.out.println("backward"); 71 | break; 72 | case 2: 73 | System.out.println("both"); 74 | break; 75 | case -1: 76 | System.out.println("invalid"); 77 | break; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/LexicographicOrder.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/23. 7 | * 头条:求一串数字的字典序 8 | */ 9 | public class LexicographicOrder { 10 | public static void main(String[] args) { 11 | Scanner scanner = new Scanner(System.in); 12 | int n = scanner.nextInt(); 13 | int m = scanner.nextInt(); 14 | int[] array = new int[n]; 15 | int num = 0; 16 | int flag = 0; 17 | int sonFlag = 0; 18 | boolean canContinue = true; 19 | for (int i = 1; i < n + 1 && i < 10; i++) { 20 | flag = i; 21 | while (flag <= n) { 22 | sonFlag = flag; 23 | while (num < n && sonFlag <= n) { 24 | if (flag >= 10) { 25 | canContinue = sonFlag < flag + flag / i; 26 | } else { 27 | canContinue = sonFlag == flag; 28 | } 29 | if (!canContinue) { 30 | break; 31 | } 32 | array[num] = sonFlag; 33 | num++; 34 | sonFlag++; 35 | } 36 | flag = flag * 10; 37 | } 38 | } 39 | System.out.println(array[m - 1]); 40 | scanner.close(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/StringBigNumberMulti.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/1. 7 | * java计算两个字符串大数的乘积 8 | */ 9 | public class StringBigNumberMulti { 10 | public static void main(String[] args) { 11 | Scanner in = new Scanner(System.in); 12 | String line = in.nextLine(); 13 | String[] values = line.trim().split(" "); 14 | if (values.length != 2) { 15 | return; 16 | } 17 | String str1 = values[0]; 18 | String str2 = values[1]; 19 | 20 | int len1 = str1.length(); 21 | int len2 = str2.length(); 22 | 23 | char[] s1 = str1.toCharArray(); 24 | char[] s2 = str2.toCharArray(); 25 | 26 | // 高低位对调 27 | covertdata(s1, len1); 28 | covertdata(s2, len2); 29 | 30 | System.out.println("乘数:" + str1); 31 | System.out.println("乘数:" + str2); 32 | multiply(s1, len1, s2, len2); 33 | 34 | } 35 | 36 | public static void covertdata(char data[], int len) { 37 | //高低位对调 38 | for (int i = 0; i < len / 2; i++) { 39 | data[i] += data[len - 1 - i]; 40 | data[len - 1 - i] = (char) (data[i] - data[len - 1 - i]); 41 | data[i] = (char) (data[i] - data[len - 1 - i]); 42 | } 43 | } 44 | 45 | public static void multiply(char a[], int alen, char b[], int blen) { 46 | // 两数乘积位数不会超过乘数位数和+ 3位 47 | int csize = alen + blen + 3; 48 | // 开辟乘积数组 49 | int[] c = new int[csize]; 50 | // 乘积数组填充0 51 | for (int ii = 0; ii < csize; ii++) { 52 | c[ii] = 0; 53 | } 54 | // 对齐逐位相乘 55 | for (int j = 0; j < blen; j++) { 56 | for (int i = 0; i < alen; i++) { 57 | c[i + j] += Integer.parseInt(String.valueOf(a[i])) * Integer.parseInt(String.valueOf(b[j])); 58 | } 59 | } 60 | int m = 0; 61 | // 进位处理 62 | for (m = 0; m < csize; m++) { 63 | int carry = c[m] / 10; 64 | c[m] = c[m] % 10; 65 | if (carry > 0) 66 | c[m + 1] += carry; 67 | } 68 | // 找到最高位 69 | for (m = csize - 1; m >= 0; ) { 70 | if (c[m] > 0) 71 | break; 72 | m--; 73 | } 74 | // 由最高位开始打印乘积 75 | System.out.print("乘积:"); 76 | for (int n = 0; n <= m; n++) { 77 | System.out.print(c[m - n]); 78 | } 79 | System.out.println(""); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/TestDistribution.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | /** 7 | * Created by wangzhongqiu on 2017/8/22. 8 | * 头条2017秋招 9 | * 头条的2017校招开始了!为了这次校招,我们组织了一个规模宏大的出题团队。每个出题人都出了一些有趣的题目,而我们现在想把这些题目组合成若干场考试出来。在选题之前,我们对题目进行了盲审,并定出了每道题的难度系数。一场考试包含3道开放性题目,假设他们的难度从小到大分别为a, b, c,我们希望这3道题能满足下列条件: 10 | * a<= b<= c 11 | * b - a<= 10 12 | * c - b<= 10 13 | * 所有出题人一共出了n道开放性题目。现在我们想把这n道题分布到若干场考试中(1场或多场,每道题都必须使用且只能用一次),然而由于上述条件的限制,可能有一些考试没法凑够3道题,因此出题人就需要多出一些适当难度的题目来让每场考试都达到要求。然而我们出题已经出得很累了,你能计算出我们最少还需要再出几道题吗? 14 | */ 15 | public class TestDistribution { 16 | public static void main(String[] args) { 17 | Scanner scan = new Scanner(System.in); 18 | int n = scan.nextInt(); 19 | int[] arr = new int[n]; 20 | for (int i = 0; i < n; i++) { 21 | arr[i] = scan.nextInt(); 22 | } 23 | int res = 0; 24 | Arrays.sort(arr); 25 | for (int i = 0; i < n; i++) { 26 | //判断第二个数和第一个数字的差 大于20则跳过(还需要出2道题目) 27 | if (i + 1 < n && arr[i + 1] - arr[i] > 20) { 28 | res += 2; 29 | continue; 30 | //如果不到与20但是大于10,则还需要出一道题 31 | } else if (i + 1 < n && arr[i + 1] - arr[i] > 10) { 32 | res += 1; 33 | i = i + 1; 34 | continue; 35 | //如果在10以内的情况 36 | } else if (i + 1 < n) { 37 | //判断第三个数字比第二个数字大多少 38 | //10以内 39 | if (i + 2 < n && arr[i + 2] - arr[i + 1] <= 10) { 40 | i = i + 2; 41 | //10以外 42 | } else if (i + 2 < n) { 43 | res += 1; 44 | i = i + 1; 45 | //不存在第三个数字 46 | } else { 47 | res += 1; 48 | i = i + 1; 49 | } 50 | } else { 51 | //如果没有下一个了就+2 52 | res += 2; 53 | } 54 | } 55 | System.out.println(res); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/swordatoffer/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming.swordatoffer; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/28. 7 | * 剑指offer:斐波那契数列 8 | */ 9 | public class Fibonacci { 10 | public static void main(String[] args) { 11 | Scanner scan = new Scanner(System.in); 12 | int n = scan.nextInt(); 13 | System.out.println(Fibonacci(n)); 14 | } 15 | 16 | public static int Fibonacci(int n) { 17 | if (n == 0) { 18 | return 0; 19 | } else if (n < 3) { 20 | return 1; 21 | } else { 22 | return Fibonacci(n - 1) + Fibonacci(n - 2); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/swordatoffer/OrderedArraySearch.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming.swordatoffer; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/17. 7 | * 剑指offer 8 | * 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上往下递增的顺序排序。 9 | * 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 10 | */ 11 | public class OrderedArraySearch { 12 | public static void main(String[] args) { 13 | Scanner sc = new Scanner(System.in); 14 | int rows = sc.nextInt(); 15 | int columns = sc.nextInt(); 16 | int[][] array = new int[columns][rows]; 17 | for (int i = 0; i < array.length; i++) { 18 | for (int j = 0; j < array[i].length; j++) { 19 | array[i][j] = sc.nextInt(); 20 | } 21 | } 22 | OrderedArraySearch orderedArraySearch = new OrderedArraySearch(); 23 | System.out.print(orderedArraySearch.find(7, array)); 24 | } 25 | 26 | public boolean find(int target, int[][] array) { 27 | boolean found = false; 28 | int rows = array.length; 29 | int columns = array[0].length; 30 | if (array != null && rows > 0 && columns > 0) { 31 | int r = 0; 32 | int c = columns - 1; 33 | while (r < rows && c >= 0) { 34 | int temp = array[r][c]; 35 | if (target > temp) { 36 | r++; 37 | } else if (target < temp) { 38 | c--; 39 | } else { 40 | found = true; 41 | break; 42 | } 43 | } 44 | } 45 | return found; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/swordatoffer/ReplaceSpace.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming.swordatoffer; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/20. 5 | * 剑指offer:替换字符串中的所有空格为"%20" 6 | */ 7 | public class ReplaceSpace { 8 | public static void main(String[] args) { 9 | StringBuffer s = new StringBuffer(" "); 10 | String str = replaceSpace(s); 11 | System.out.print(str); 12 | } 13 | 14 | public static String replaceSpace(StringBuffer str) { 15 | String[] arr = new String[str.length()]; 16 | int arrMark = 0; 17 | int j = -1; 18 | for (int i = 0; i < str.length(); i++) { 19 | if (str.charAt(i) == ' ') { 20 | if (i > j + 1) { 21 | arr[arrMark++] = str.substring(j + 1, i); 22 | j = i; 23 | } 24 | arr[arrMark++] = "%20"; 25 | j = i; 26 | } else if (i == str.length() - 1) { 27 | arr[arrMark++] = str.substring(j + 1, i + 1); 28 | } 29 | } 30 | StringBuilder sb = new StringBuilder(); 31 | for (int i = 0; i < arr.length; i++) { 32 | if (arr[i] != null) { 33 | sb.append(arr[i]); 34 | } 35 | } 36 | return sb.toString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/swordatoffer/RevolvingArray.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming.swordatoffer; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/22. 5 | * 剑指offer:旋转数组 6 | * 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 7 | * 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 8 | */ 9 | public class RevolvingArray { 10 | public static void main(String[] args) { 11 | RevolvingArray revolvingArray = new RevolvingArray(); 12 | int[] array = {3,2}; 13 | int i = revolvingArray.minNumberInRotateArray(array); 14 | } 15 | 16 | public int minNumberInRotateArray(int[] array) { 17 | if (array.length == 0) { 18 | return 0; 19 | } 20 | int flag = 0; 21 | int[] newArray = new int[array.length]; 22 | for (int i = 1; i < array.length; i++) { 23 | if (array[i] < array[i - 1]) { 24 | flag = i; 25 | break; 26 | } 27 | } 28 | int newArrayNum = 0; 29 | for (int i = flag; i < array.length; i++) { 30 | newArray[newArrayNum++] = array[i]; 31 | } 32 | for (int i = 0; i < flag; i++) { 33 | newArray[newArrayNum++] = array[i]; 34 | } 35 | return newArray[0]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/programming/swordatoffer/TwoStackReplaceQueen.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.programming.swordatoffer; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/22. 7 | * 剑指offer:两个栈实现队列的功能。实现push和pop方法 8 | */ 9 | public class TwoStackReplaceQueen { 10 | public static void main(String[] args) { 11 | TwoStackReplaceQueen test = new TwoStackReplaceQueen(); 12 | test.push(1); 13 | test.push(2); 14 | test.push(3); 15 | System.out.println(test.pop()); 16 | System.out.println(test.pop()); 17 | System.out.println(test.pop()); 18 | System.out.println(test.pop()); 19 | } 20 | 21 | Stack stack1 = new Stack(); 22 | Stack stack2 = new Stack(); 23 | 24 | public void push(int node) { 25 | if (stack1.isEmpty()) { 26 | stack1.push(node); 27 | } else { 28 | while (!stack1.isEmpty()) { 29 | stack2.push(stack1.pop()); 30 | } 31 | stack1.push(node); 32 | while (!stack2.isEmpty()) { 33 | stack1.push(stack2.pop()); 34 | } 35 | } 36 | } 37 | 38 | public int pop() { 39 | return stack1.pop(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/search/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.search; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/17. 5 | * 二分查找,时间复杂度为O(logn) 6 | * 元素必须是有序的,如果是无序的则要先进行排序操作。 7 | * 折半查找的前提条件是需要有序表顺序存储,对于静态查找表,一次排序后不再变化,折半查找能得到不错的效率。 8 | * 但对于需要频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,那就不建议使用。 9 | */ 10 | public class BinarySearch { 11 | public static void main(String[] args) { 12 | int columns = 5; 13 | int[] array = new int[columns]; 14 | for (Integer i = 0; i < columns; i++) { 15 | array[i] = i; 16 | } 17 | boolean result = binarySearchAdapt(array, 4, 0, array.length - 1); 18 | System.out.print(result); 19 | } 20 | 21 | //二分查找(折半查找) 22 | public static boolean binarySearch(int a[], int value, int low, int high) { 23 | int mid; 24 | while (low <= high) { 25 | mid = (low + high) / 2; 26 | if (a[mid] == value) 27 | return true; 28 | if (a[mid] > value) 29 | high = mid - 1; 30 | if (a[mid] < value) 31 | low = mid + 1; 32 | } 33 | return false; 34 | } 35 | 36 | //二分查找,递归版本 37 | public static int binarySearchRecursion(int a[], int value, int low, int high) { 38 | int mid = (low + high) / 2; 39 | if (a[mid] == value) 40 | return mid; 41 | else if (a[mid] > value) 42 | return binarySearchRecursion(a, value, low, mid - 1); 43 | else 44 | return binarySearchRecursion(a, value, mid + 1, high); 45 | } 46 | 47 | //差值二分查找,自适应 48 | //对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找算法的平均性能比折半查找要好的多。 49 | //反之,数组中如果分布非常不均匀,那么插值查找未必是很合适的选择。 50 | public static boolean binarySearchAdapt(int a[], int value, int low, int high) { 51 | int mid; 52 | while (low <= high) { 53 | mid = low + (value - a[low]) / (a[high] - a[low]) * (high - low); 54 | if (a[mid] == value) 55 | return true; 56 | if (a[mid] > value) 57 | high = mid - 1; 58 | if (a[mid] < value) 59 | low = mid + 1; 60 | } 61 | return false; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/search/SequentialSearch.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.search; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/17. 5 | * 顺序查找,时间复杂度为O(n) 6 | */ 7 | public class SequentialSearch { 8 | public static void main(String[] args) { 9 | int columns = 5; 10 | int rows = 5; 11 | int[][] array = new int[columns][rows]; 12 | for (Integer i = 0; i < columns; i++) { 13 | for (Integer j = 0; j < rows; j++) { 14 | array[i][j] = Integer.parseInt(i.toString() + j.toString()); 15 | } 16 | } 17 | boolean result=find(21,array); 18 | System.out.print(result); 19 | } 20 | 21 | public static boolean find(int target, int[][] array) { 22 | for (int x = 0; x < array.length; x++) { 23 | for (int y = 0; y < array[x].length; y++) { 24 | if (array[x][y] == target) return true; 25 | } 26 | } 27 | return false; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.sort; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/15. 5 | * 冒泡排序:它重复地走访过要排序的数列,一次比较两个元素, 6 | * 如果他们的顺序错误就把他们交换过来。 7 | * 走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 8 | * 时间复杂度为O(n^2),是一种稳定的排序算法 9 | */ 10 | public class BubbleSort { 11 | public static void main(String[] args) { 12 | int[] a = {9, 8, 7, 6, 5, 4, 3, 2, 1}; 13 | bubbleSort(a); 14 | for (int o : a) { 15 | System.out.print(o + ","); 16 | } 17 | } 18 | 19 | public static void bubbleSort(int[] a) { 20 | int temp = 0; 21 | for (int i = a.length - 1; i > 0; i--) { 22 | for (int j = 0; j < i; j++) { 23 | if (a[j] > a[j + 1]) { 24 | temp = a[j + 1]; 25 | a[j + 1] = a[j]; 26 | a[j] = temp; 27 | } 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/sort/HeapSort.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.sort; 2 | 3 | import zhongqiu.common.utils.CommonUtils; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * Created by wangzhongqiu on 2017/8/15. 9 | * 堆排序的基本思想是:将待排序序列构造成一个大顶堆, 10 | * 从最后一个非叶子结点开始,从左至右,从下至上进行调整。 11 | * 此时,整个序列的最大值就是堆顶的根节点。 12 | * 将其与末尾元素进行交换,此时末尾就为最大值。 13 | * 然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了 14 | * 不稳定排序,时间复杂度为O(nlogn)。堆排序是一种选择排序 15 | * 堆的存储:一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。 16 | * 它的左右子结点下标分别为2 * i + 1和2 * i + 2。 17 | */ 18 | public class HeapSort { 19 | public static void main(String[] args) { 20 | int[] a = {9, 12, 17, 30, 50, 20, 60, 65, 4, 49}; 21 | HeapSort heapSort = new HeapSort(); 22 | heapSort.HeapSort(a, a.length - 1); 23 | System.out.print(Arrays.toString(a)); 24 | } 25 | 26 | void HeapAdjust(int H[], int start, int end) { 27 | int temp = H[start]; 28 | for (int i = 2 * start + 1; i <= end; i = 2 * i + 1) { 29 | //因为假设根结点的序号为0而不是1,所以i结点左孩子和右孩子分别为2i+1和2i+2 30 | if (i < end && H[i] < H[i + 1])//左右孩子的比较 31 | { 32 | i++;//i为较大的记录的下标 33 | } 34 | //左右孩子中获胜者与父亲的比较 35 | if (temp > H[i]) { 36 | break; 37 | } 38 | //将孩子结点上位,则以孩子结点的位置进行下一轮的筛选 39 | H[start] = H[i]; 40 | start = i; 41 | } 42 | H[start] = temp; //插入最开始不和谐的元素 43 | } 44 | 45 | void HeapSort(int A[], int n) { 46 | //先建立大顶堆 47 | for (int i = n / 2 - 1; i >= 0; i--) { 48 | HeapAdjust(A, i, n - 1); 49 | } 50 | //进行排序 51 | for (int i = n; i > 0; i--) { 52 | //最后一个元素和第一元素进行交换 53 | int temp = A[i]; 54 | A[i] = A[0]; 55 | A[0] = temp; 56 | //然后将剩下的无序元素继续调整为大顶堆 57 | HeapAdjust(A, 0, i - 1); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/sort/InsertSort.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.sort; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/9. 5 | * 插入排序 6 | * 入排序的基本操作就是将一个数据插入到已经排好序的有序数据中, 7 | * 从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序, 8 | * 时间复杂度为O(n^2)。是稳定的排序方法。 9 | */ 10 | public class InsertSort { 11 | public static void main(String[] args) { 12 | int[] a = {9, 8, 7, 6, 5, 4, 3, 2, 1}; 13 | insertSort(a, 0, a.length - 1); 14 | for (int o : a) { 15 | System.out.print(o + ","); 16 | } 17 | } 18 | 19 | public static void insertSort(int[] arr, int low, int high) { 20 | int i, j, target, n = arr.length; 21 | //假定第一个元素被放到了正确的位置上,这样,仅需遍历1 - n-1 22 | for (i = low + 1; i < high + 1; i++) { 23 | j = i; 24 | target = arr[j]; 25 | while (j > 0 && target < arr[j - 1]) { 26 | arr[--j] = arr[j - 1]; 27 | } 28 | arr[j] = target; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/algorithm/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.algorithm.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/8/11. 7 | * 归并排序,是稳定的排序,时间复杂度为O(nlogn),空间复杂度为 O(n) 8 | * 思想:分治,递归,2路归并 9 | * 需要一块额外的内存空间来协助完成两个有序块的合并 10 | * 只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。 11 | * 然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。 12 | * 最后把排序好的临时数列放回(覆盖)待排序数列即可 13 | */ 14 | public class MergeSort { 15 | public static void main(String[] args) { 16 | int a[] = {51, 46, 20, 18, 65, 97, 82, 30, 77, 50}; 17 | mergeSort(a, 0, a.length - 1); 18 | System.out.println("排序结果:" + Arrays.toString(a)); 19 | } 20 | 21 | public static void merge(int[] a, int low, int mid, int high) { 22 | int[] temp = new int[high - low + 1]; 23 | int i = low;// 左指针 24 | int j = mid + 1;// 右指针 25 | int k = 0; 26 | // 把较小的数先移到新数组中 27 | while (i <= mid && j <= high) { 28 | if (a[i] < a[j]) { 29 | temp[k++] = a[i++]; 30 | } else { 31 | temp[k++] = a[j++]; 32 | } 33 | } 34 | // 把左边剩余的数移入数组 35 | while (i <= mid) { 36 | temp[k++] = a[i++]; 37 | } 38 | // 把右边边剩余的数移入数组 39 | while (j <= high) { 40 | temp[k++] = a[j++]; 41 | } 42 | // 把新数组中的数覆盖nums数组 43 | for (int k2 = 0; k2 < temp.length; k2++) { 44 | a[k2 + low] = temp[k2]; 45 | } 46 | } 47 | 48 | public static void mergeSort(int[] a, int low, int high) { 49 | int mid = (low + high) / 2; 50 | if (low < high) { 51 | // 左边 52 | mergeSort(a, low, mid); 53 | // 右边 54 | mergeSort(a, mid + 1, high); 55 | // 左右归并 56 | merge(a, low, mid, high); 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/applet/AppletDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.applet; 2 | 3 | import java.applet.Applet; 4 | import java.awt.Graphics; 5 | 6 | //Applet 7 | //http://www.runoob.com/java/java-applet-basics.html 8 | @SuppressWarnings("serial") 9 | public class AppletDemo extends Applet{ 10 | public void paint (Graphics g) 11 | { 12 | g.drawString ("Hello World", 25, 50); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/applet/AppletTest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Insert title here 6 | 7 | 8 |


9 | 10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/applet/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | /** 5 | * @author Administrator 6 | * 7 | */ 8 | package zhongqiu.common.base.applet; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/collections/ArrayDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.collections; 2 | 3 | //数组相关 4 | public class ArrayDemo { 5 | public static int[] intArray={1,2,3,4}; // 首选的方法 6 | 7 | // public static int doubleArray2[]; 效果相同,但不是首选方法。沿用c/c++的写法 8 | 9 | public static void main(String[] args) { 10 | initArray(); 11 | printArray(intArray); 12 | intArray = reverse(intArray); 13 | printArray(intArray); 14 | } 15 | 16 | // 创建数组 17 | public static void initArray() { 18 | int[] intArray1 = new int[10]; 19 | int[] intArray2={1,2,3,4}; 20 | } 21 | 22 | // 数组作为函数的参数 23 | public static void printArray(int[] array) { 24 | for (int i = 0; i < array.length; i++) { 25 | System.out.print(array[i] + " "); 26 | } 27 | } 28 | 29 | // 数组作为函数的返回值 30 | public static int[] reverse(int[] list) { 31 | int[] result = new int[list.length]; 32 | 33 | for (int i = 0, j = result.length - 1; i < list.length; i++, j--) { 34 | result[j] = list[i]; 35 | } 36 | return result; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/collections/ArraysDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.collections; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | //Arrays类相关 7 | public class ArraysDemo { 8 | public static void main(String[] args) { 9 | byte[] test1 = { 23, 34 }; 10 | 11 | byte[] test2 = { 23, 34 }; 12 | 13 | int[] test3 = { 4, 5, 6, 7 }; 14 | 15 | // 根据第二个参数作为索引找出对应的下标,二分法查找算法 16 | System.out.println(Arrays.binarySearch(test3, 7)); 17 | 18 | // toString方法 19 | System.out.println(test1.toString()); 20 | System.out.println(Arrays.toString(test1));// 重写Tostring方法 21 | 22 | // Equals方法 23 | System.out.println(test1.equals(test2)); 24 | System.out.println(Arrays.equals(test1, test2));// 重写了Equals方法 25 | System.out.println(test1 == test2); 26 | System.out.println(test1.getClass()); 27 | // fill方法 28 | // 将指定的 byte 值分配给指定byte型数组指定范围中的每个元素。 29 | Arrays.fill(test1, 0, 1, (byte) 56); 30 | System.out.println(Arrays.toString(test1)); 31 | 32 | // hashCode方法 33 | System.out.println(test1.hashCode()); 34 | System.out.println(Arrays.hashCode(test1));// 基于指定数组的内容返回哈希码 35 | 36 | // aslist 37 | List list = Arrays.asList(test1); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/collections/CollectionPo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.collections; 2 | 3 | public class CollectionPo { 4 | public Integer age; 5 | public Integer sex; 6 | public String name; 7 | 8 | public CollectionPo() { 9 | 10 | } 11 | 12 | public CollectionPo(Integer sex, String name, Integer age) { 13 | this.name = name; 14 | this.sex = sex; 15 | this.age = age; 16 | } 17 | 18 | public Integer getAge() { 19 | return age; 20 | } 21 | 22 | public void setAge(Integer age) { 23 | this.age = age; 24 | } 25 | 26 | public Integer getSex() { 27 | return sex; 28 | } 29 | 30 | public void setSex(Integer sex) { 31 | this.sex = sex; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/collections/CollectionsDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.collections; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author wangzhongqiu 7 | * @date 2018/1/22. 8 | */ 9 | public class CollectionsDemo { 10 | private static ArrayList lists = new ArrayList<>(); 11 | private static HashSet set = new HashSet<>(); 12 | private static HashMap map = new HashMap<>(); 13 | 14 | public static void main(String[] args) { 15 | lists.add("1"); 16 | lists.add("2"); 17 | lists.add("3"); 18 | set.add("1"); 19 | map.put("1", "1"); 20 | 21 | List synlist = Collections.synchronizedList(lists); 22 | Set synset = Collections.synchronizedSet(set); 23 | Map synmap = Collections.synchronizedMap(map); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/collections/SetDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.collections; 2 | 3 | import java.util.HashSet; 4 | import java.util.LinkedHashSet; 5 | import java.util.TreeSet; 6 | 7 | //set 8 | //Set和List的区别 9 | //1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。 10 | //2. Set检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。 11 | //3. List和数组类似,可以动态增长,根据实际存储的数据的长度自动增长List的长度。 12 | // 查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。 13 | public class SetDemo { 14 | public static void main(String[] args) { 15 | 16 | } 17 | 18 | // HashSet类按照哈希算法来存取集合中的对象,存取速度比较快。HashSet类还有一个子类LinkedHashSet类,它不仅实现了哈希算法,而且实现了链表数据结构。 19 | HashSet hSet = new HashSet<>();//非线程安全 20 | 21 | LinkedHashSet linkedHashSet=new LinkedHashSet<>(); 22 | // TreeSet类实现了SortedSet接口,具有排序功能。TreeSet支持两种排序方式:自然排序和客户化排序,在默认情况下TreeSet采用自然排序方式。 23 | TreeSet tSet = new TreeSet<>();//非线程安全 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/collections/StackDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.collections; 2 | 3 | import java.util.Stack; 4 | 5 | //栈,Vector的子类 6 | public class StackDemo { 7 | // 把元素放入栈顶 8 | static void showpush(Stack st, int a) { 9 | st.push(new Integer(a)); 10 | System.out.println("push(" + a + ")"); 11 | System.out.println("stack: " + st); 12 | } 13 | 14 | // 从栈顶删除元素 15 | static void showpop(Stack st) { 16 | System.out.print("pop -> "); 17 | // 判断栈是否为空 18 | if (st.empty()) { 19 | System.out.println("Stack is empty."); 20 | } else { 21 | Integer a = (Integer) st.pop(); 22 | System.out.println(a); 23 | System.out.println("stack: " + st); 24 | } 25 | } 26 | 27 | // 查看栈顶元素 28 | static void showpeek(Stack st) { 29 | System.out.print("peek -> "); 30 | if (st.empty()) { 31 | System.out.println("Stack is empty."); 32 | } else { 33 | Integer a = (Integer) st.peek(); 34 | System.out.println(a); 35 | System.out.println("stack: " + st); 36 | } 37 | } 38 | 39 | // 查询指定元素 40 | static void showsearch(Stack st, int i) { 41 | System.out.print("search -> " + i); 42 | Integer index = (Integer) st.search(i); 43 | System.out.println("--index -> " + index); 44 | System.out.println("stack: " + st); 45 | } 46 | 47 | public static void main(String args[]) { 48 | Stack st = new Stack(); 49 | System.out.println("stack: " + st); 50 | showpush(st, 42); 51 | showpush(st, 66); 52 | showpeek(st); 53 | showsearch(st, 66); 54 | showsearch(st, 88); 55 | showpop(st); 56 | showpop(st); 57 | showpop(st); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/gc/GCCollector.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.gc; 2 | 3 | 4 | /* 5 | (a)Serial收集器 6 | 串行收集器是最古老,最稳定以及效率高的收集器,可能会产生较长的停顿,只使用一个线程去回收。 7 | 新生代、老年代使用串行回收;新生代复制算法、老年代标记-压缩;垃圾收集的过程中会Stop The World(服务暂停) 8 | 参数控制:-XX:+UseSerialGC 串行收集器 9 | (b)吐量优先的并行收集器 10 | -XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。 11 | -XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。 12 | -XX:+UseParallelOldGC:配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。Parallel Old是Serial Old的并行版本 13 | -XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间,如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值。 14 | -XX:+UseAdaptiveSizePolicy:设置此选项后,并行收集器会自动选择年轻代区大小和相应的Survivor区比例, 15 | 以达到目标系统规定的最低相应时间或者收集频率等,此值建议使用并行收集器时,一直打开。 16 | (c)响应时间优先的并发收集器 17 | -XX:+UseParNewGC:ParNew是Serial的并行版本。 18 | 设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上,JVM会根据系统配置自行设置,所以无需再设置此值。 19 | (d)CMS收集器。优点:并发收集、低停顿。缺点:产生大量空间碎片、并发阶段会降低吞吐量 20 | -XX:+UseConcMarkSweepGC 设置年老代使用CMS收集器 21 | -XX:+UseCMSCompactAtFullCollection FullGC后,进行一次碎片整理;整理过程是独占的,会引起停顿时间变长 22 | -XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理 23 | -XX:ParallelCMSThreads 设定CMS的线程数量(一般情况约等于可用CPU数量) 24 | (e)G1收集器 25 | G1收集器采用标记整理算法。 可预测停顿,能让使用者明确指定在一个长度为N毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒 26 | -XX:+UseG1GC 27 | */ 28 | public class GCCollector { 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/gc/classload/ClassLoadDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.gc.classload; 2 | 3 | public class ClassLoadDemo { 4 | static { 5 | System.out.println("ClassLoadDemo静态初始化块执行了!"); 6 | } 7 | 8 | public static void main(String[] args) throws ClassNotFoundException { 9 | // 一、类加载过程: 10 | // 1、寻找jre目录,寻找jvm.dll,并初始化JVM; 11 | // 2、产生一个Bootstrap Loader(启动类加载器); 12 | // 3、Bootstrap Loader自动加载Extended Loader(标准扩展类加载器),并将其父Loader设为Bootstrap 13 | // Loader。 14 | // 4、Bootstrap Loader自动加载AppClass Loader(系统类加载器),并将其父Loader设为Extended 15 | // Loader。 16 | // 5、最后由AppClass Loader加载HelloWorld类。 17 | ClassLoader loader1 = ClassLoadDemo.class.getClassLoader(); 18 | System.out.println(loader1); 19 | System.out.println(loader1.getParent()); 20 | System.out.println(loader1.getParent().getParent()); 21 | 22 | // 二、类加载有三种方式: 23 | // 1、命令行启动应用时候由JVM初始化加载 24 | // 2、通过Class.forName()方法动态加载 25 | // 3、通过ClassLoader.loadClass()方法动态加载 26 | ClassLoader loader2 = ClassLoadDemo.class.getClassLoader(); 27 | System.out.println(loader2); 28 | // 使用ClassLoader.loadClass()来加载类,不会执行初始化块 29 | // loader2.loadClass("zhongqiu.test.Test"); 30 | // 使用Class.forName()来加载类,默认会执行初始化块 31 | // Class.forName("zhongqiu.test.Test"); 32 | // 使用Class.forName()来加载类,并指定ClassLoader,初始化时不执行静态块 33 | Class.forName("zhongqiu.test.Test", false, loader2); 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/gc/classload/MyClassLoader.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.gc.classload; 2 | 3 | import java.net.MalformedURLException; 4 | import java.net.URL; 5 | import java.net.URLClassLoader; 6 | 7 | public class MyClassLoader { 8 | @SuppressWarnings("resource") 9 | public static void main(String[] args) 10 | throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException { 11 | URL url = new URL("file:/D:/javaworkspace/JavaCommon/src/"); 12 | ClassLoader myloader = new URLClassLoader(new URL[] { url }); 13 | Class c = myloader.loadClass("zhongqiu.common.base.classload.Test"); 14 | Test t3 = (Test) c.newInstance(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/gc/classload/Test.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.gc.classload; 2 | 3 | public class Test { 4 | static { 5 | System.out.println("Test静态初始化块执行了!"); 6 | } 7 | Integer i; 8 | Integer j; 9 | 10 | Test() { 11 | 12 | } 13 | 14 | Test(Integer i, Integer j) { 15 | setI(i); 16 | setJ(j); 17 | } 18 | 19 | public Integer getJ() { 20 | return j; 21 | } 22 | 23 | public void setJ(Integer j) { 24 | this.j = j; 25 | } 26 | 27 | public int getI() { 28 | return i; 29 | } 30 | 31 | public void setI(Integer i) { 32 | this.i = i; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/gc/classload/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Administrator 3 | * http://www.importnew.com/23742.html 4 | (1)什么是类加载。 5 | 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内, 然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。 6 | (2)类的生命周期 7 | 加载,查找并加载类的二进制数据,在Java堆中也创建一个java.lang.Class类的对象 8 | 连接,连接又包含三块内容:验证、准备、解析。 9 | 1)验证,文件格式、元数据、字节码、符号引用验证;2)准备,为类的静态变量分配内存,并将其初始化为默认值;3)解析,把类中的符号引用转换为直接引用 10 | 初始化,为类的静态变量赋予正确的初始值 11 | 使用,new出对象程序中使用 12 | 卸载,执行垃圾回收 13 | (3)JVM初始化步骤 14 | 假如这个类还没有被加载和连接,则程序先加载并连接该类 15 | 假如该类的直接父类还没有被初始化,则先初始化其直接父类 16 | 假如类中有初始化语句,则系统依次执行这些初始化语句 17 | (4)类初始化时机:只有当对类的主动使用的时候才会导致类的初始化,类的主动使用包括以下六种: 18 | (a)创建类的实例,也就是new的方式(b)访问某个类或接口的静态变量,或者对该静态变量赋值(c)调用类的静态方法 19 | (d)反射(如Class.forName(“com.shengsiyuan.Test”))(e)初始化某个类的子类,则其父类也会被初始化 20 | (f)Java虚拟机启动时被标明为启动类的类(Java Test),直接使用java.exe命令来运行某个主类 21 | (5)结束生命周期 22 | 执行了System.exit()方法;程序正常执行结束;程序在执行过程中遇到了异常或错误而异常终止;由于操作系统出现错误而导致Java虚拟机进程终止 23 | (6)类加载器 24 | 启动类加载器:Bootstrap ClassLoader,负责加载存放在JDK\jre\lib(JDK代表JDK的安装目录).启动类加载器是无法被Java程序直接引用的 25 | 扩展类加载器:Extension ClassLoader.开发者可以直接使用扩展类加载器 26 | 应用程序类加载器:Application ClassLoader 27 | 自定义的类加载器 28 | (7)JVM类加载机制 29 | (a)全盘负责,当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入 30 | (b)父类委托,先让父类加载器试图加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类 31 | (c)缓存机制,缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区寻找该Class,只有缓存区不存在, 32 | 系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓存区。这就是为什么修改了Class后,必须重启JVM,程序的修改才会生效 33 | (8)类加载的三种方式 34 | */ 35 | package zhongqiu.common.base.gc.classload; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/CopyFile.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class CopyFile { 8 | static public void main(String args[]) throws Exception { 9 | if (args.length < 2) { 10 | System.err.println("Usage: java CopyFile infile outfile"); 11 | System.exit(1); 12 | } 13 | 14 | String infile = args[0]; 15 | String outfile = args[1]; 16 | 17 | FileInputStream fin = new FileInputStream(infile); 18 | FileOutputStream fout = new FileOutputStream(outfile); 19 | 20 | FileChannel fcin = fin.getChannel(); 21 | FileChannel fcout = fout.getChannel(); 22 | 23 | ByteBuffer buffer = ByteBuffer.allocate(1024); 24 | 25 | while (true) { 26 | buffer.clear(); 27 | 28 | int r = fcin.read(buffer); 29 | 30 | if (r == -1) { 31 | break; 32 | } 33 | 34 | buffer.flip(); 35 | 36 | fcout.write(buffer); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/CreateArrayBuffer.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class CreateArrayBuffer { 8 | static public void main(String args[]) throws Exception { 9 | byte array[] = new byte[1024]; 10 | 11 | ByteBuffer buffer = ByteBuffer.wrap(array); 12 | 13 | buffer.put((byte) 'a'); 14 | buffer.put((byte) 'b'); 15 | buffer.put((byte) 'c'); 16 | 17 | buffer.flip(); 18 | 19 | System.out.println((char) buffer.get()); 20 | System.out.println((char) buffer.get()); 21 | System.out.println((char) buffer.get()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/CreateBuffer.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class CreateBuffer { 8 | static public void main(String args[]) throws Exception { 9 | ByteBuffer buffer = ByteBuffer.allocate(1024); 10 | 11 | buffer.put((byte) 'a'); 12 | buffer.put((byte) 'b'); 13 | buffer.put((byte) 'c'); 14 | 15 | buffer.flip(); 16 | 17 | System.out.println((char) buffer.get()); 18 | System.out.println((char) buffer.get()); 19 | System.out.println((char) buffer.get()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/FastCopyFile.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class FastCopyFile { 8 | static public void main(String args[]) throws Exception { 9 | if (args.length < 2) { 10 | System.err.println("Usage: java FastCopyFile infile outfile"); 11 | System.exit(1); 12 | } 13 | 14 | String infile = args[0]; 15 | String outfile = args[1]; 16 | 17 | FileInputStream fin = new FileInputStream(infile); 18 | FileOutputStream fout = new FileOutputStream(outfile); 19 | 20 | FileChannel fcin = fin.getChannel(); 21 | FileChannel fcout = fout.getChannel(); 22 | 23 | ByteBuffer buffer = ByteBuffer.allocateDirect(1024); 24 | 25 | while (true) { 26 | buffer.clear(); 27 | 28 | int r = fcin.read(buffer); 29 | 30 | if (r == -1) { 31 | break; 32 | } 33 | 34 | buffer.flip(); 35 | 36 | fcout.write(buffer); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/MultiPortEcho.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.nio.*; 6 | import java.nio.channels.*; 7 | import java.util.*; 8 | 9 | public class MultiPortEcho { 10 | private int ports[]; 11 | private ByteBuffer echoBuffer = ByteBuffer.allocate(1024); 12 | 13 | public MultiPortEcho(int ports[]) throws IOException { 14 | this.ports = ports; 15 | 16 | go(); 17 | } 18 | 19 | private void go() throws IOException { 20 | // Create a new selector 21 | Selector selector = Selector.open(); 22 | 23 | // Open a listener on each port, and register each one 24 | // with the selector 25 | for (int i = 0; i < ports.length; ++i) { 26 | ServerSocketChannel ssc = ServerSocketChannel.open(); 27 | ssc.configureBlocking(false); 28 | ServerSocket ss = ssc.socket(); 29 | InetSocketAddress address = new InetSocketAddress(ports[i]); 30 | ss.bind(address); 31 | 32 | SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT); 33 | 34 | System.out.println("Going to listen on " + ports[i]); 35 | } 36 | 37 | while (true) { 38 | int num = selector.select(); 39 | 40 | Set selectedKeys = selector.selectedKeys(); 41 | Iterator it = selectedKeys.iterator(); 42 | 43 | while (it.hasNext()) { 44 | SelectionKey key = (SelectionKey) it.next(); 45 | 46 | if ((key.readyOps() & SelectionKey.OP_ACCEPT) 47 | == SelectionKey.OP_ACCEPT) { 48 | // Accept the new connection 49 | ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); 50 | SocketChannel sc = ssc.accept(); 51 | sc.configureBlocking(false); 52 | 53 | // Add the new connection to the selector 54 | SelectionKey newKey = sc.register(selector, SelectionKey.OP_READ); 55 | it.remove(); 56 | 57 | System.out.println("Got connection from " + sc); 58 | } else if ((key.readyOps() & SelectionKey.OP_READ) 59 | == SelectionKey.OP_READ) { 60 | // Read the data 61 | SocketChannel sc = (SocketChannel) key.channel(); 62 | 63 | // Echo data 64 | int bytesEchoed = 0; 65 | while (true) { 66 | echoBuffer.clear(); 67 | 68 | int r = sc.read(echoBuffer); 69 | 70 | if (r <= 0) { 71 | break; 72 | } 73 | 74 | echoBuffer.flip(); 75 | 76 | sc.write(echoBuffer); 77 | bytesEchoed += r; 78 | } 79 | 80 | System.out.println("Echoed " + bytesEchoed + " from " + sc); 81 | 82 | it.remove(); 83 | } 84 | 85 | } 86 | 87 | //System.out.println( "going to clear" ); 88 | // selectedKeys.clear(); 89 | //System.out.println( "cleared" ); 90 | } 91 | } 92 | 93 | static public void main(String args[]) throws Exception { 94 | if (args.length <= 0) { 95 | System.err.println("Usage: java MultiPortEcho port [port port ...]"); 96 | System.exit(1); 97 | } 98 | 99 | int ports[] = new int[args.length]; 100 | 101 | for (int i = 0; i < args.length; ++i) { 102 | ports[i] = Integer.parseInt(args[i]); 103 | } 104 | 105 | new MultiPortEcho(ports); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/ReadAndShow.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class ReadAndShow { 8 | static public void main(String args[]) throws Exception { 9 | FileInputStream fin = new FileInputStream("readandshow.txt"); 10 | FileChannel fc = fin.getChannel(); 11 | 12 | ByteBuffer buffer = ByteBuffer.allocate(1024); 13 | 14 | //通过通道读取数据到缓存区 15 | fc.read(buffer); 16 | 17 | buffer.flip(); 18 | 19 | int i = 0; 20 | while (buffer.remaining() > 0) { 21 | byte b = buffer.get(); 22 | System.out.println("Character " + i + ": " + ((char) b)); 23 | i++; 24 | } 25 | 26 | fin.close(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/SliceBuffer.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class SliceBuffer { 8 | static public void main(String args[]) throws Exception { 9 | ByteBuffer buffer = ByteBuffer.allocate(10); 10 | 11 | for (int i = 0; i < buffer.capacity(); ++i) { 12 | buffer.put((byte) i); 13 | } 14 | 15 | buffer.position(3); 16 | buffer.limit(7); 17 | 18 | ByteBuffer slice = buffer.slice(); 19 | 20 | for (int i = 0; i < slice.capacity(); ++i) { 21 | byte b = slice.get(i); 22 | b *= 11; 23 | slice.put(i, b); 24 | } 25 | 26 | buffer.position(0); 27 | buffer.limit(buffer.capacity()); 28 | 29 | while (buffer.remaining() > 0) { 30 | System.out.println(buffer.get()); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/TypesInByteBuffer.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class TypesInByteBuffer { 8 | static public void main(String args[]) throws Exception { 9 | ByteBuffer buffer = ByteBuffer.allocate(64); 10 | 11 | buffer.putInt(30); 12 | buffer.putLong(7000000000000L); 13 | buffer.putDouble(Math.PI); 14 | 15 | buffer.flip(); 16 | 17 | System.out.println(buffer.getInt()); 18 | System.out.println(buffer.getLong()); 19 | System.out.println(buffer.getDouble()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/UseCharsets.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | import java.nio.charset.*; 7 | 8 | public class UseCharsets { 9 | static public void main(String args[]) throws Exception { 10 | String inputFile = "samplein.txt"; 11 | String outputFile = "sampleout.txt"; 12 | 13 | RandomAccessFile inf = new RandomAccessFile(inputFile, "r"); 14 | RandomAccessFile outf = new RandomAccessFile(outputFile, "rw"); 15 | long inputLength = new File(inputFile).length(); 16 | 17 | FileChannel inc = inf.getChannel(); 18 | FileChannel outc = outf.getChannel(); 19 | 20 | MappedByteBuffer inputData = 21 | inc.map(FileChannel.MapMode.READ_ONLY, 0, inputLength); 22 | 23 | Charset latin1 = Charset.forName("ISO-8859-1"); 24 | CharsetDecoder decoder = latin1.newDecoder(); 25 | CharsetEncoder encoder = latin1.newEncoder(); 26 | 27 | CharBuffer cb = decoder.decode(inputData); 28 | 29 | // Process char data here 30 | 31 | ByteBuffer outputData = encoder.encode(cb); 32 | 33 | outc.write(outputData); 34 | 35 | inf.close(); 36 | outf.close(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/UseFileLocks.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class UseFileLocks { 8 | static private final int start = 10; 9 | static private final int end = 20; 10 | 11 | static public void main(String args[]) throws Exception { 12 | new Thread(new Runnable() { 13 | public void run() { 14 | // Get file channel 15 | RandomAccessFile raf = null; 16 | try { 17 | raf = new RandomAccessFile("usefilelocks.txt", "rw"); 18 | } catch (FileNotFoundException e) { 19 | // TODO Auto-generated catch block 20 | e.printStackTrace(); 21 | } 22 | FileChannel fc = raf.getChannel(); 23 | 24 | // Get lock 25 | System.out.println("trying to get lock"); 26 | FileLock lock = null; 27 | try { 28 | lock = fc.lock(start, end, false); 29 | } catch (IOException e) { 30 | // TODO Auto-generated catch block 31 | e.printStackTrace(); 32 | } 33 | System.out.println("got lock!"); 34 | 35 | // Pause 36 | System.out.println("pausing"); 37 | try { 38 | Thread.sleep(5000); 39 | } catch (InterruptedException ie) { 40 | } 41 | 42 | // Release lock 43 | System.out.println("going to release lock"); 44 | try { 45 | lock.release(); 46 | } catch (IOException e) { 47 | // TODO Auto-generated catch block 48 | e.printStackTrace(); 49 | } 50 | System.out.println("released lock"); 51 | 52 | try { 53 | raf.close(); 54 | } catch (IOException e) { 55 | // TODO Auto-generated catch block 56 | e.printStackTrace(); 57 | } 58 | } 59 | }).start(); 60 | 61 | new Thread(new Runnable() { 62 | public void run() { 63 | // Get file channel 64 | RandomAccessFile raf = null; 65 | try { 66 | raf = new RandomAccessFile("usefilelocks.txt", "rw"); 67 | } catch (FileNotFoundException e) { 68 | // TODO Auto-generated catch block 69 | e.printStackTrace(); 70 | } 71 | FileChannel fc = raf.getChannel(); 72 | 73 | // Get lock 74 | System.out.println("trying to get lock"); 75 | FileLock lock = null; 76 | try { 77 | lock = fc.lock(start, end, false); 78 | } catch (IOException e) { 79 | // TODO Auto-generated catch block 80 | e.printStackTrace(); 81 | } 82 | System.out.println("got lock!"); 83 | 84 | // Release lock 85 | System.out.println("going to release lock"); 86 | try { 87 | lock.release(); 88 | } catch (IOException e) { 89 | // TODO Auto-generated catch block 90 | e.printStackTrace(); 91 | } 92 | System.out.println("released lock"); 93 | 94 | try { 95 | raf.close(); 96 | } catch (IOException e) { 97 | // TODO Auto-generated catch block 98 | e.printStackTrace(); 99 | } 100 | } 101 | }).start(); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/UseFloatBuffer.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.nio.*; 4 | 5 | public class UseFloatBuffer { 6 | static public void main(String args[]) throws Exception { 7 | FloatBuffer buffer = FloatBuffer.allocate(10); 8 | 9 | for (int i = 0; i < buffer.capacity(); ++i) { 10 | float f = (float) Math.sin((((float) i) / 10) * (2 * Math.PI)); 11 | buffer.put(f); 12 | } 13 | 14 | buffer.flip(); 15 | 16 | while (buffer.hasRemaining()) { 17 | float f = buffer.get(); 18 | System.out.println(f); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/UseMappedFile.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class UseMappedFile { 8 | static private final int start = 0; 9 | static private final int size = 1024; 10 | 11 | static public void main(String args[]) throws Exception { 12 | RandomAccessFile raf = new RandomAccessFile("writesomebytes.txt", "rw"); 13 | FileChannel fc = raf.getChannel(); 14 | 15 | MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 16 | start, size); 17 | 18 | mbb.put(0, (byte) 97); 19 | mbb.put(1023, (byte) 122); 20 | 21 | raf.close(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/UseScatterGather.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.nio.*; 6 | import java.nio.channels.*; 7 | 8 | public class UseScatterGather { 9 | static private final int firstHeaderLength = 2; 10 | static private final int secondHeaderLength = 4; 11 | static private final int bodyLength = 6; 12 | 13 | static public void main(String args[]) throws Exception { 14 | if (args.length != 1) { 15 | System.err.println("Usage: java UseScatterGather port"); 16 | System.exit(1); 17 | } 18 | 19 | int port = Integer.parseInt(args[0]); 20 | 21 | ServerSocketChannel ssc = ServerSocketChannel.open(); 22 | InetSocketAddress address = new InetSocketAddress(port); 23 | ssc.socket().bind(address); 24 | 25 | int messageLength = 26 | firstHeaderLength + secondHeaderLength + bodyLength; 27 | 28 | ByteBuffer buffers[] = new ByteBuffer[3]; 29 | buffers[0] = ByteBuffer.allocate(firstHeaderLength); 30 | buffers[1] = ByteBuffer.allocate(secondHeaderLength); 31 | buffers[2] = ByteBuffer.allocate(bodyLength); 32 | 33 | SocketChannel sc = ssc.accept(); 34 | 35 | while (true) { 36 | 37 | // Scatter-read into buffers 38 | int bytesRead = 0; 39 | while (bytesRead < messageLength) { 40 | long r = sc.read(buffers); 41 | bytesRead += r; 42 | 43 | System.out.println("r " + r); 44 | for (int i = 0; i < buffers.length; ++i) { 45 | ByteBuffer bb = buffers[i]; 46 | System.out.println("b " + i + " " + bb.position() + " " + bb.limit()); 47 | } 48 | } 49 | 50 | // Process message here 51 | 52 | // Flip buffers 53 | for (int i = 0; i < buffers.length; ++i) { 54 | ByteBuffer bb = buffers[i]; 55 | bb.flip(); 56 | } 57 | 58 | // Scatter-write back out 59 | long bytesWritten = 0; 60 | while (bytesWritten < messageLength) { 61 | long r = sc.write(buffers); 62 | bytesWritten += r; 63 | } 64 | 65 | // Clear buffers 66 | for (int i = 0; i < buffers.length; ++i) { 67 | ByteBuffer bb = buffers[i]; 68 | bb.clear(); 69 | } 70 | 71 | System.out.println(bytesRead + " " + bytesWritten + " " + messageLength); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/WriteSomeBytes.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.nio; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | 7 | public class WriteSomeBytes { 8 | static private final byte message[] = { 83, 111, 109, 101, 32, 98, 121, 116, 101, 115, 46 }; 9 | 10 | static public void main(String args[]) throws Exception { 11 | FileOutputStream fout = new FileOutputStream("writesomebytes.txt"); 12 | 13 | // 新建通道 14 | FileChannel fc = fout.getChannel(); 15 | 16 | ByteBuffer buffer = ByteBuffer.allocate(1024); 17 | 18 | for (int i = 0; i < message.length; ++i) { 19 | // 写入缓冲区 20 | buffer.put(message[i]); 21 | } 22 | 23 | buffer.flip(); 24 | // 从缓冲区写入通道 25 | fc.write(buffer); 26 | 27 | fout.close(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/nio/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | /** 5 | * @author zhongqiu 6 | *https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html 7 | *重要概念:通道,缓冲区 8 | *区别:io是面向io,面向流的;nio是面向缓冲区的。 9 | *传统的socket IO中,需要为每个连接创建一个线程,当并发的连接数量非常巨大时,线程所占用的栈内存和CPU线程切换的开销将非常巨大。 10 | *使用NIO,不再需要为每个线程创建单独的线程,可以用一个含有限数量线程的线程池,甚至一个线程来为任意数量的连接服务。 11 | *由于线程数量小于连接数量,所以每个线程进行IO操作时就不能阻塞,如果阻塞的话,有些连接就得不到处理,NIO提供了这种非阻塞的能力。 12 | *一、三个状态变量:position,limit,capacity。position<=limit,limit<=capacity 13 | * buffer.flip(),改变position和limit的值。 14 | *二、访问方法:get()和put() 15 | * get() 和 put() 的相对方法和绝对方法,相对方法在调用后会改变position的值,绝对方法不会改变 16 | *三、缓存区的使用。FileChannel.read() 和FileChannel. write() 调用得到了极大的简化, 17 | * 因为许多工作细节都由缓冲区完成了。buffer. clear() 和 buffer.flip() 方法用于让缓冲区在读和写之间切换。buffer.rewind(),重绕 18 | *四、缓冲区分配和包装。分配:ByteBuffer.allocate( 1024 ); 19 | * 包装:byte array[] = new byte[1024]; 20 | ByteBuffer buffer = ByteBuffer.wrap( array ); 21 | *五、缓冲区分片和数据共享。缓冲区和子缓冲区共享同一个底层数据数组 22 | * 分片(子缓冲区):buffer.position( 3 );buffer.limit( 7 );ByteBuffer slice = buffer.slice(); 23 | *六、只读缓冲区。通过调用缓冲区的 asReadOnlyBuffer() 方法,将任何常规缓冲区转换为只读缓冲区, 24 | * 这个方法返回一个与原缓冲区完全相同的缓冲区(并与其共享数据),只不过它是只读的。 不能将只读的缓冲区转换为可写的缓冲区。 25 | *七、直接和间接缓冲区。 FastCopyFile.java。ByteBuffer buffer = ByteBuffer.allocateDirect( 1024 ); 26 | *八、将文件映射到内存。FileChannel.map 27 | *九、分散和聚集。缓冲区数组、 28 | *十、网络IO。ServerSocketChannel,SocketChannel,ServerSocket,selector, 29 | *十一、文件锁定。FileChannel.lock()获取对此通道的文件的独占锁定;FileLock.release()释放锁 30 | */ 31 | package zhongqiu.common.base.nio; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author zhongqiu 3 | * 参考资料:http://www.runoob.com/java/java-stack-class.html 4 | * 实例: http://www.runoob.com/java/java-examples.html 5 | * java基础: 6 | * (1)基本数据类型:8个基本类型;值类型和引用类型,常量池,intern()方法,stringbuilder 7 | * (2)运算符操作:a++,++a,三元运算符,instanceof运算符,位运算符,&&和&的区别 8 | * (3)异常:错误和异常,异常分为运行时异常和非运行时异常。Throwable,Error,Exception,RuntimeException。throws和throw的区别 9 | * (4)String,StringBuffer,StringBuilder区别:stringbuilder的方法使用 10 | * (5)Number类型相关:对应基本类型的封装类。是否实现了常量池技术,哪些实现了,哪些没有实现,有哪些限制.存在于.class文件中,在运行期被JVM装载,并且可以扩充 11 | * (6)随机数。Math.random():生成随机的六位字符串 12 | * (7)反射机制 13 | * (7)关键字用法:final,volatile,native,static,transient,break,continue 14 | * (8)object类相关方法。equals四个特性:自反,对称,一致,传递;hashcode:三个协定,需要重写的情景;getclass,toString;notify;wait 15 | * (9)内部类。常规内部类,静态内部类,私有内部类,局部内部类,匿名内部类,内部类中的变量访问形式 16 | * (10)switch。case 1,2写法错误;支持switch int型和字符串型;default不是必须的;break不写会导致执行匹配之后的所有case代码 17 | *

18 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 19 | * (1)多线程 20 | * (2)Nio 21 | * (3)集合 22 | * (4)GC 23 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 24 | * (1)Date相关 25 | * (2)正则相关 26 | * (4)序列化 Serialize 27 | * (5)网络编程 socket,tcp/ip,http 28 | * (6)发邮件 send mail 29 | */ 30 | package zhongqiu.common.base; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/CallableTest.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | import java.util.Date; 4 | import java.util.concurrent.ExecutionException; 5 | 6 | /** 7 | * Created by wangzhongqiu on 2017/7/16. 8 | */ 9 | public class CallableTest { 10 | public static void main(String[] args) throws InterruptedException, ExecutionException { 11 | Date begin = new Date(); 12 | Calculate calculate = new Calculate(); 13 | int c = 0; 14 | 15 | //异步计算 16 | int two = 0; 17 | RunnableDemo runnableDemo = new RunnableDemo(); 18 | runnableDemo.setCalculate(calculate); 19 | new Thread(runnableDemo, "有返回值的线程").start(); 20 | int one = calculate.calOne(); 21 | while (!runnableDemo.isDone()) { 22 | } 23 | two = runnableDemo.getResult(); 24 | 25 | //求和 26 | c = one + two; 27 | Date end = new Date(); 28 | System.out.println("计算结果:" + c); 29 | long aaa = end.getTime() - begin.getTime(); 30 | System.out.println("计算耗时:" + aaa); 31 | } 32 | 33 | static class Calculate { 34 | public int calOne() throws InterruptedException { 35 | Thread.sleep(10000); 36 | return 10; 37 | } 38 | 39 | public int calTwo() throws InterruptedException { 40 | Thread.sleep(5000); 41 | return 5; 42 | } 43 | 44 | } 45 | 46 | static class RunnableDemo implements Runnable { 47 | private Calculate calculate; 48 | 49 | private Integer result; 50 | 51 | private volatile boolean done = false; 52 | 53 | 54 | @Override 55 | public void run() { 56 | try { 57 | result = calculate.calTwo(); 58 | done = true; 59 | } catch (InterruptedException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | public Calculate getCalculate() { 65 | return calculate; 66 | } 67 | 68 | public void setCalculate(Calculate calculate) { 69 | this.calculate = calculate; 70 | } 71 | 72 | public Integer getResult() { 73 | return result; 74 | } 75 | 76 | public void setResult(Integer result) { 77 | this.result = result; 78 | } 79 | 80 | public boolean isDone() { 81 | return done; 82 | } 83 | 84 | public void setDone(boolean done) { 85 | this.done = done; 86 | } 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/PrintABC.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | // 建立三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。 4 | // 主要考察obj.wait()和obj.notify() 的用法 5 | public class PrintABC extends Thread { 6 | public static void main(String[] args) throws InterruptedException { 7 | PrintABC pa = new PrintABC("A"); 8 | PrintABC pb = new PrintABC("B"); 9 | PrintABC pc = new PrintABC("C"); 10 | pa.setWait(pc); 11 | pb.setWait(pa); 12 | pc.setWait(pb); 13 | 14 | new Thread(pa).start(); 15 | Thread.sleep(100); // 确保按顺序A、B、C执行 16 | new Thread(pb).start(); 17 | Thread.sleep(100); 18 | new Thread(pc).start(); 19 | Thread.sleep(100); 20 | } 21 | 22 | private String name; 23 | private PrintABC wait; 24 | 25 | public PrintABC getWait() { 26 | return wait; 27 | } 28 | 29 | public void setWait(PrintABC wait) { 30 | this.wait = wait; 31 | } 32 | 33 | private PrintABC(String name) { 34 | this.name = name; 35 | } 36 | 37 | @Override 38 | public void run() { 39 | int count = 10; 40 | while (count > 0) { 41 | synchronized (wait) { 42 | synchronized (this) { 43 | System.out.println(name); 44 | count--; 45 | // notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束, 46 | // 自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。 47 | this.notify(); 48 | } 49 | try { 50 | // Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权, 51 | // 主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。 52 | wait.wait(); 53 | } catch (InterruptedException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/SimpleDateFormatDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | import java.text.DateFormat; 4 | import java.text.ParseException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | 8 | /** 9 | * @author wangzhongqiu 10 | * @date 2018/1/23. 11 | */ 12 | public class SimpleDateFormatDemo { 13 | private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 14 | 15 | public static String formatDate(Date date) throws ParseException { 16 | return sdf.format(date); 17 | } 18 | 19 | public static Date parse(String strDate) throws ParseException { 20 | 21 | return sdf.parse(strDate); 22 | } 23 | 24 | public static class SimpleDateFormatTest extends Thread { 25 | @Override 26 | public void run() { 27 | int i = 0; 28 | while (i < 100) { 29 | try { 30 | this.join(2000); 31 | } catch (InterruptedException e1) { 32 | e1.printStackTrace(); 33 | } 34 | try { 35 | System.out.println(this.getName() + ":" + parse("2013-05-24 06:02:20")); 36 | } catch (ParseException e) { 37 | e.printStackTrace(); 38 | } 39 | i++; 40 | } 41 | } 42 | } 43 | 44 | public static class ThreadLocalDateUtilTest extends Thread { 45 | @Override 46 | public void run() { 47 | int i = 0; 48 | while (i < 100) { 49 | try { 50 | this.join(2000); 51 | } catch (InterruptedException e1) { 52 | e1.printStackTrace(); 53 | } 54 | try { 55 | System.out.println(this.getName() + ":" + ThreadLocalDateUtil.parse("2013-05-24 06:02:20")); 56 | } catch (ParseException e) { 57 | e.printStackTrace(); 58 | } 59 | i++; 60 | } 61 | } 62 | } 63 | 64 | public static void main(String[] args) { 65 | // for (int i = 0; i < 3; i++) { 66 | // new SimpleDateFormatTest().start(); 67 | // } 68 | for (int i = 0; i < 3; i++) { 69 | new ThreadLocalDateUtilTest().start(); 70 | } 71 | } 72 | 73 | //性能较好的解决方案,threadlocal 74 | static class ThreadLocalDateUtil { 75 | private static final String date_format = "yyyy-MM-dd HH:mm:ss"; 76 | private static ThreadLocal threadLocal = new ThreadLocal(); 77 | 78 | public static DateFormat getDateFormat() { 79 | DateFormat df = threadLocal.get(); 80 | if (df == null) { 81 | df = new SimpleDateFormat(date_format); 82 | threadLocal.set(df); 83 | } 84 | return df; 85 | } 86 | 87 | public static String formatDate(Date date) throws ParseException { 88 | return getDateFormat().format(date); 89 | } 90 | 91 | public static Date parse(String strDate) throws ParseException { 92 | return getDateFormat().parse(strDate); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/ThreadDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | /** 4 | * @author wangzhongqiu 5 | * @date 2018/1/31. 6 | */ 7 | public class ThreadDemo { 8 | public static void main(String[] args) { 9 | BlockRunnable blockRunnable = new BlockRunnable(); 10 | SpinRunnable spinRunnable = new SpinRunnable(); 11 | Thread thread = new Thread(spinRunnable, "new"); 12 | thread.start(); 13 | try { 14 | thread.join(); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | try { 19 | Thread.sleep(1000 * 3); 20 | } catch (InterruptedException e) { 21 | e.printStackTrace(); 22 | } 23 | System.out.println("thread线程状态:" + thread.getState()); 24 | thread.interrupt(); 25 | try { 26 | Thread.sleep(1000 * 3); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | System.out.println("thread线程interrupt状态:" + Thread.interrupted()); 31 | System.out.println("thread线程interrupt状态:" + thread.isInterrupted()); 32 | System.out.println("thread线程状态:" + thread.getState()); 33 | } 34 | 35 | //阻塞thread 36 | public static class BlockRunnable implements Runnable { 37 | private volatile int count = 50; 38 | private static Object lock = new Object(); 39 | 40 | @Override 41 | public void run() { 42 | System.out.println("thread线程开始运行"); 43 | synchronized (lock) { 44 | try { 45 | lock.wait(1000 * 10); 46 | } catch (InterruptedException e) { 47 | System.out.println("thread线程状态:" + Thread.currentThread().getState()); 48 | } 49 | } 50 | System.out.println("thread线程运行结束"); 51 | } 52 | } 53 | 54 | //自旋thread 55 | public static class SpinRunnable implements Runnable { 56 | private volatile int count = 50; 57 | private static Object lock = new Object(); 58 | 59 | @Override 60 | public void run() { 61 | System.out.println("thread线程开始运行"); 62 | while (true) { 63 | 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/ThreadLocalDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | import java.util.Date; 4 | 5 | public class ThreadLocalDemo { 6 | private static final ThreadLocal threadLocal = new ThreadLocal(); 7 | private static final ThreadLocal threadLocal1 = new ThreadLocal(); 8 | 9 | public static void main(String[] args) { 10 | Integer integer = 111; 11 | threadLocal.set(integer); 12 | threadLocal1.set(integer); 13 | Thread thread = Thread.currentThread(); 14 | Date now = new Date("20170102"); 15 | Integer a=threadLocal.get(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/VolatileDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | //Volatile修饰符 4 | 5 | //http://www.cnblogs.com/wangzhongqiu/p/6475357.html 6 | /* 7 | * Volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。 8 | * 这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。 9 | * 一个 volatile 对象引用可能是 null。 10 | */ 11 | 12 | import zhongqiu.common.base.MathRandomDemo; 13 | 14 | import java.util.Hashtable; 15 | import java.util.Map; 16 | import java.util.concurrent.ExecutorService; 17 | import java.util.concurrent.Executors; 18 | 19 | public class VolatileDemo { 20 | /* 21 | * 常情况下,在一个线程调用 run() 方法(在 Runnable 开启的线程),在另一个线程调用 stop() 方法。 如果 第一行 中缓冲区的 22 | * active 值被使用,那么在 第二行 的 active 值为 false 时循环不会停止。 但是以上代码中我们使用了 volatile 修饰 23 | * active,所以该循环会停止。 24 | */ 25 | public static Hashtable num = new Hashtable<>(); 26 | 27 | public static class Model { 28 | Integer a; 29 | Integer b; 30 | } 31 | 32 | public Model model; 33 | 34 | public Model getModel() { 35 | return model; 36 | } 37 | 38 | public void setModel(Model model) { 39 | this.model = model; 40 | } 41 | 42 | public void init() { 43 | model.a = 1; 44 | model.b = 2; 45 | } 46 | 47 | public void change() { 48 | model.a = 3; 49 | model.b = model.a; 50 | } 51 | 52 | public void print() { 53 | String key = model.a.toString() + model.b.toString(); 54 | if (num.keySet().contains(key)) { 55 | num.put(key, num.get(key) + 1); 56 | } else { 57 | num.put(key, 1); 58 | } 59 | } 60 | 61 | public static void test1() { 62 | final VolatileDemo test = new VolatileDemo(); 63 | VolatileDemo.Model model = new VolatileDemo.Model(); 64 | model.a = 1; 65 | model.b = 2; 66 | test.setModel(model); 67 | ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1); 68 | ExecutorService fixedThreadPool1 = Executors.newFixedThreadPool(1); 69 | ExecutorService fixedThreadPool2 = Executors.newFixedThreadPool(1); 70 | for (int i = 0; i < 1; i++) { 71 | fixedThreadPool.execute(new Runnable() { 72 | @Override 73 | public void run() { 74 | while (true) { 75 | test.change(); 76 | } 77 | } 78 | }); 79 | fixedThreadPool1.execute(new Runnable() { 80 | @Override 81 | public void run() { 82 | while (true) { 83 | test.init(); 84 | } 85 | } 86 | }); 87 | fixedThreadPool2.execute(new Runnable() { 88 | @Override 89 | public void run() { 90 | while (true) { 91 | test.print(); 92 | } 93 | } 94 | }); 95 | } 96 | try { 97 | Thread.sleep(10000); 98 | } catch (InterruptedException e) { 99 | e.printStackTrace(); 100 | } 101 | for (Map.Entry entry : num.entrySet()) { 102 | System.out.println("key:" + entry.getKey() + "--value:" + entry.getValue()); 103 | } 104 | } 105 | 106 | public static void main(String[] args) { 107 | test1(); 108 | } 109 | } 110 | 111 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/VolatileDemo2.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | import java.util.Hashtable; 4 | import java.util.Map; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | 8 | /** 9 | * Created by Administrator on 2017/12/24. 10 | */ 11 | public class VolatileDemo2 { 12 | public static Hashtable num = new Hashtable<>(); 13 | private Integer a = 1; 14 | private Integer b = 2; 15 | 16 | public void init() { 17 | a = 1; 18 | b = 2; 19 | } 20 | 21 | public void change() { 22 | a = 1; 23 | b = 2; 24 | a = 3; 25 | b = a; 26 | } 27 | 28 | public void print() { 29 | String key = a.toString() + b.toString(); 30 | if (num.keySet().contains(key)) { 31 | num.put(key, num.get(key) + 1); 32 | } else { 33 | num.put(key, 1); 34 | } 35 | } 36 | 37 | public static void test1() { 38 | final VolatileDemo2 test = new VolatileDemo2(); 39 | ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1); 40 | ExecutorService fixedThreadPool1 = Executors.newFixedThreadPool(1); 41 | ExecutorService fixedThreadPool2 = Executors.newFixedThreadPool(1); 42 | for (int i = 0; i < 1; i++) { 43 | fixedThreadPool.execute(new Runnable() { 44 | @Override 45 | public void run() { 46 | while (true) { 47 | test.change(); 48 | } 49 | } 50 | }); 51 | fixedThreadPool1.execute(new Runnable() { 52 | @Override 53 | public void run() { 54 | while (true) { 55 | test.init(); 56 | } 57 | } 58 | }); 59 | fixedThreadPool2.execute(new Runnable() { 60 | @Override 61 | public void run() { 62 | while (true) { 63 | test.print(); 64 | } 65 | } 66 | }); 67 | } 68 | try { 69 | Thread.sleep(5000); 70 | } catch (InterruptedException e) { 71 | e.printStackTrace(); 72 | } 73 | for (Map.Entry entry : num.entrySet()) { 74 | System.out.println("key:" + entry.getKey() + "--value:" + entry.getValue()); 75 | } 76 | } 77 | 78 | public static void main(String[] args) { 79 | test1(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/WaitNotifyDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.base.thread; 2 | 3 | // wait和notify的demo 4 | //如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待这个对象的控制权的状态。 5 | //如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。 6 | //如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。 7 | 8 | //任何一个时刻,对象的控制权(monitor)只能被一个线程拥有。 9 | //无论是执行对象的wait、notify还是notifyAll方法,必须保证当前运行的线程取得了该对象的控制权(monitor) 10 | //如果在没有控制权的线程里执行对象的以上三种方法,就会报java.lang.IllegalMonitorStateException异常。 11 | //JVM基于多线程,默认情况下不能保证运行时线程的时序性 12 | 13 | public class WaitNotifyDemo { 14 | public static void main(String[] args) { 15 | 16 | // wait和notify的Demo 17 | System.out.println("Main Thread Run!"); 18 | WaitNotifyDemo test = new WaitNotifyDemo(); 19 | NotifyThread notifyThread = test.new NotifyThread("notify01"); 20 | WaitThread waitThread01 = test.new WaitThread("waiter01"); 21 | WaitThread waitThread02 = test.new WaitThread("waiter02"); 22 | WaitThread waitThread03 = test.new WaitThread("waiter03"); 23 | notifyThread.start(); 24 | waitThread01.start(); 25 | // waitThread02.start(); 26 | // waitThread03.start(); 27 | } 28 | 29 | private StringBuilder flag =new StringBuilder("true"); 30 | 31 | class NotifyThread extends Thread { 32 | public NotifyThread(String name) { 33 | super(name); 34 | } 35 | 36 | public void run() { 37 | try { 38 | sleep(100000);// 推迟3秒钟通知 39 | } catch (InterruptedException e) { 40 | e.printStackTrace(); 41 | } 42 | synchronized (flag) { 43 | flag.replace(1, flag.length(), "false"); 44 | flag.notifyAll(); 45 | } 46 | } 47 | }; 48 | 49 | class WaitThread extends Thread { 50 | public WaitThread(String name) { 51 | super(name); 52 | } 53 | 54 | public void run() { 55 | synchronized (flag) { 56 | while (flag.toString().equals("true")) { 57 | System.out.println(getName() + " begin waiting!"); 58 | long waitTime = System.currentTimeMillis(); 59 | try { 60 | flag.wait(); 61 | } catch (InterruptedException e) { 62 | e.printStackTrace(); 63 | } 64 | waitTime = System.currentTimeMillis() - waitTime; 65 | System.out.println("wait time :" + waitTime); 66 | } 67 | System.out.println(getName() + " end waiting!"); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/base/thread/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @author zhongqiu 3 | * 并发,线程相关 4 | * (1)同步Synchronized。可重入独占锁,非公平锁,每个线程都去竞争锁,不管排队先后。 5 | * 等待锁的实现方式:自旋锁,挂起等待,混合锁 6 | * (2)thread。implements Runnable。持有对象Runnable target,ThreadLocal.ThreadLocalMap threadLocals,threadStatus 7 | * 初始化方式(runable,thread),runable和thread的区别 8 | * 线程的状态:New、Runnable(包括操作系统的Ready和Running)、Blocked、Waiting、Timed waiting、Terminated 9 | * new Thread(),变为New状态 10 | * start() ,变为Runnable状态,创建新的线程在栈空间中开辟新的空间.if (threadStatus != 0) 抛出异常 11 | * run() ,不创建新的线程,直接在当前线程执行 thread的run方法 12 | * yield() ,使线程变成ready状态,从新和其他ready状态的线程参与cpu的竞争 13 | * isAlive(),如果线程已经启动且尚未终止,则为活动状态。介于Runnable和Terminated中间,都属于活动状态 14 | * join() ,B线程执行A.join(). B获取A对象的锁; 循环判断a.isAlive(),是则调用a.wait(0),进入Waiting状态。 15 | * 等A线程执行完毕,jvm执行notify_all(a);B线程重新获取到A对象的控制权,继续执行 16 | * sleep() ,当前线程进入TIMED_WAITING状态,不释放监视器锁 17 | * interrupt(),不会中断一个正在运行的线程。如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞, 18 | * 它将接收到一个中断信号,提早地终结被阻塞状态,变成Runnable状态,抛出异常InterruptedException,继续往下执行 19 | * 如果线程没有被阻塞,这时调用interrupt()将不起作用 20 | * isInterrupted()->isInterrupted(false),查看线程的中断位,不清除 21 | * Thread.interrupted()->currentThread().isInterrupted(true).等价于 Thread.currentThread().interrupt() 22 | * 静态方法,清除中断位,返回清除的中断位,只有当前线程才可以清除自己的中断位 23 | * 多线程异步计算获取计算结果 24 | * (2) Object 25 | * wait() ,等价于wait(0),使持有该对象的线程把该对象的控制权交出去,然后处于等待这个对象的控制权的状态。 26 | * 当前线程进入Waiting或者Timed waiting 27 | * notify() ,通知某个正在等待这个对象的控制权的线程可以继续运行。 28 | * notifyall(),通知所有等待这个对象控制权的线程继续运行。 29 | * 经典面试题(三个线程交替打印10次ABC) 30 | * (3)ThreadLocal。ThreadLocalMap,Entry(ThreadLocal k, Object v)。thread持有ThreadLocalMap对象 31 | * get: Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t); 32 | * ThreadLocalMap.Entry e = map.getEntry(this); return (T)e.value; 33 | * (4)SimpleDateFormat。SimpleDateFormat继承了DateFormat,在DateFormat中定义了一个protected属性的 Calendar类的对象:calendar。 34 | * calendar是一个有状态的变量,format方法中执行了calendar.setTime(date)这条语句改变了calendar, 35 | * 稍后,calendar还会用到(在subFormat方法里) 36 | * 解决办法:需要的时候创建新实例,使用同步锁synchronized(sdf),threadlocal 37 | * (5)Volatile关键字。 38 | * 缓存一致性:内存,cpu高速缓存,总线锁机制,缓存一致性协议(Intel 的MESI协议),共享变量。 39 | * 内存模型:次序规则,锁定规则,volatile变量规则,线程启动规则,线程终止规则,对象终结规则 40 | * 并发编程的三个概念:原子性问题,可见性问题,有序性问题 41 | * Java内存模型:1、在java内存模型中,也会存在缓存一致性问题和指令重排序的问题。 42 | * 2、所有的变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(类似于前面的高速缓存)。 43 | * 线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。 44 | * 3、原子性:java中,对基本数据类型的变量的读取和赋值操作是原子性操作 。通过synchronized和Lock实现更大范围的原子性 45 | * 4、可见性:通过volatile实现 46 | * 5、有序性:happens-before原则(先行发生原则) 47 | * Volatile说明:volatile关键字能禁止指令重排序,所以volatile能在一定程度上保证有序性。 48 | * volatile保证原子性吗?不能!!! 49 | * 50 | * 51 | */ 52 | package zhongqiu.common.base.thread; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/Boxing.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5; 2 | 3 | public class Boxing { 4 | public static void main(String[] args) { 5 | integerBoxing(); 6 | } 7 | 8 | public static void autoBoxing() { 9 | /* 10 | * 一般我们要创建一个类的对象实例的时候,我们会这样: 11 | * 12 | * Class a = new Class(parameter); 13 | * 14 | * 当我们创建一个Integer对象时,却可以这样: 15 | * 16 | * Integer i = 100; (注意:不是 int i = 100; ) 17 | * 18 | * 实际上,执行上面那句代码的时候,系统为我们执行了:Integer i = Integer.valueOf(100); 19 | * 20 | * 此即基本数据类型的自动装箱功能。 21 | * 此即基本数据类型的自动装箱功能。 22 | */ 23 | Integer i = 100; 24 | } 25 | 26 | public static void unBoxing() { 27 | // 自动拆箱(unboxing),也就是将对象中的基本数据从对象中自动取出。如下可实现自动拆箱: 28 | Integer i = 10; // 装箱 29 | int t = i; // 拆箱,实际上执行了 int t = i.intValue(); 30 | } 31 | 32 | public static void integerBoxing() { 33 | // integer源码 34 | // public static Integer valueOf(int i) { 35 | // if(i >= -128 && i <= IntegerCache.high) // 没有设置的话,IngegerCache.high 36 | // 默认是127 37 | // return IntegerCache.cache[i + 128]; 38 | // else 39 | // return new Integer(i); 40 | // } 41 | 42 | // 在-128~127 之外的数 43 | Integer i1 = 200; 44 | Integer i2 = 200; 45 | System.out.println("i1==i2: " + (i1 == i2));// 显示false 46 | // 在-128~127 之内的数 47 | Integer i3 = 100; 48 | Integer i4 = 100; 49 | System.out.println("i3==i4: " + (i3 == i4));// 显示true 50 | 51 | Integer i5 = new Integer(100); 52 | Integer i6 = new Integer(100); 53 | System.out.println("i5==i6: " + (i5 == i6));// 显示false 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/EnumDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5; 2 | 3 | import java.util.EnumSet; 4 | 5 | //枚举 6 | /* 7 | 1、普通枚举,通过name获取枚举,通过默认序号ordinal获取枚举 8 | 2、自定义枚举 9 | 3、枚举的switch用法 10 | 4、枚举实现接口 11 | 5、枚举集合的使用。java.util.EnumSet和java.util.EnumMap是两个枚举集合。 12 | EnumSet保证集合中的元素不重复;EnumMap中的key是enum类型,而value则可以是任意类型。*/ 13 | public class EnumDemo { 14 | public static void main(String[] args) { 15 | EnumSwitch(); 16 | } 17 | 18 | //普通枚举 19 | public enum Color { 20 | RED, GREEN, BLANK, YELLOW; 21 | 22 | //通过name获取枚举 23 | public static Color getByName(String name) { 24 | Color color = Color.RED; 25 | switch (name) { 26 | case "RED": 27 | color = Color.RED; 28 | break; 29 | case "GREEN": 30 | color = Color.GREEN; 31 | break; 32 | case "BLANK": 33 | color = Color.BLANK; 34 | break; 35 | case "YELLOW": 36 | color = Color.YELLOW; 37 | break; 38 | default: 39 | color = null; 40 | break; 41 | } 42 | return color; 43 | } 44 | 45 | //通过默认序号ordinal获取枚举 46 | public static Color valueOf(int ordinal) { 47 | if (ordinal >= 0 && ordinal < values().length) { 48 | return values()[ordinal]; 49 | } else { 50 | throw new IndexOutOfBoundsException("Invalid ordinal"); 51 | } 52 | } 53 | } 54 | 55 | // 自定义枚举 56 | public enum ColorExt { 57 | RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLOW("黄色", 4); 58 | // 成员变量 59 | private String name; 60 | private int index; 61 | 62 | // 构造方法 63 | private ColorExt(String name, int index) { 64 | this.name = name; 65 | this.index = index; 66 | } 67 | 68 | // 普通方法 69 | public static String getName(int index) { 70 | for (ColorExt c : ColorExt.values()) { 71 | if (c.getIndex() == index) { 72 | return c.name; 73 | } 74 | } 75 | return null; 76 | } 77 | 78 | // 覆盖方法 79 | @Override 80 | public String toString() { 81 | return this.index + "_" + this.name; 82 | } 83 | 84 | // get set 方法 85 | public String getName() { 86 | return name; 87 | } 88 | 89 | public void setName(String name) { 90 | this.name = name; 91 | } 92 | 93 | public int getIndex() { 94 | return index; 95 | } 96 | 97 | public void setIndex(int index) { 98 | this.index = index; 99 | } 100 | } 101 | 102 | // 枚举的switch用法 103 | public static void EnumSwitch() { 104 | Color color = Color.RED; 105 | System.out.println(color); 106 | switch (color) { 107 | case RED: 108 | color = Color.GREEN; 109 | System.out.println(color); 110 | break; 111 | case YELLOW: 112 | color = Color.RED; 113 | System.out.println(color); 114 | break; 115 | case GREEN: 116 | color = Color.YELLOW; 117 | System.out.println(color); 118 | break; 119 | } 120 | } 121 | 122 | // 枚举实现接口 123 | public interface Behaviour { 124 | void print(); 125 | 126 | String getInfo(); 127 | } 128 | 129 | public enum ColorImpl implements Behaviour { 130 | RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLOW("黄色", 4); 131 | // 成员变量 132 | private String name; 133 | private int index; 134 | 135 | // 构造方法 136 | private ColorImpl(String name, int index) { 137 | this.name = name; 138 | this.index = index; 139 | } 140 | 141 | // 接口方法 142 | @Override 143 | public String getInfo() { 144 | return this.name; 145 | } 146 | 147 | // 接口方法 148 | @Override 149 | public void print() { 150 | System.out.println(this.index + ":" + this.name); 151 | } 152 | } 153 | 154 | //枚举集合的使用,java.util.EnumSet和java.util.EnumMap是两个枚举集合。 155 | EnumSet repayApplyStatus = EnumSet.of(Color.BLANK,Color.GREEN,Color.RED); 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/GenericsDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5; 2 | 3 | import java.util.Random; 4 | 5 | //泛型用法。 6 | //泛型类,泛型接口,泛型方法,通配符用法extends和super 7 | /*在于Java中的泛型这一概念提出的目的,导致其只是作用于代码编译阶段, 8 | 在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说, 9 | 成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。*/ 10 | public class GenericsDemo { 11 | public static void main(String[] args) { 12 | // 泛型作为参数 13 | Container c1 = new Container("name", "findingsea"); 14 | Container c2 = new Container("age", 24); 15 | Container c3 = new Container(1.1, 2.2); 16 | Container c4 = new Container(1, new Object()); 17 | getContainer(c1); 18 | getContainer(c2); 19 | getContainer(c3); 20 | getContainerSuper(c4);// getContainerSuper(c3)会报错 21 | getContainerExtends(c1);// getContainerExtends(c2);会报错 22 | 23 | // 泛型接口 24 | FruitGenerator generator = new FruitGenerator(); 25 | System.out.println(generator.next()); 26 | System.out.println(generator.next()); 27 | 28 | // 泛型方法 29 | out("findingsea"); 30 | out(123); 31 | out("abc", "lkj", "sgh"); 32 | } 33 | 34 | // 泛型类 35 | public static class Container { 36 | private K key; 37 | private V value; 38 | 39 | public Container(K k, V v) { 40 | key = k; 41 | value = v; 42 | } 43 | 44 | public K getKey() { 45 | return key; 46 | } 47 | 48 | public void setKey(K key) { 49 | this.key = key; 50 | } 51 | 52 | public V getValue() { 53 | return value; 54 | } 55 | 56 | public void setValue(V value) { 57 | this.value = value; 58 | } 59 | } 60 | 61 | // 通配符接受泛型 62 | public static void getContainer(Container data) { 63 | System.out.println("key :" + data.getKey()); 64 | System.out.println("value :" + data.getValue()); 65 | } 66 | 67 | // 通配符接受泛型(extends用法) 68 | public static void getContainerExtends(Container data) { 69 | System.out.println("key :" + data.getKey()); 70 | System.out.println("value :" + data.getValue()); 71 | } 72 | 73 | // 通配符接受泛型(super用法) 74 | public static void getContainerSuper(Container data) { 75 | System.out.println("key :" + data.getKey()); 76 | System.out.println("value :" + data.getValue()); 77 | } 78 | 79 | // 泛型接口 80 | public interface Generator { 81 | public T next(); 82 | } 83 | 84 | // 泛型接口的实现类 85 | public static class FruitGenerator implements Generator { 86 | 87 | private String[] fruits = new String[] { "Apple", "Banana", "Pear" }; 88 | 89 | @Override 90 | public String next() { 91 | Random rand = new Random(); 92 | return fruits[rand.nextInt(3)]; 93 | } 94 | } 95 | 96 | public static R in(T t, R r) { 97 | return r; 98 | } 99 | 100 | // 泛型方法 101 | public static void out(T t) { 102 | System.out.println(t); 103 | } 104 | 105 | // 泛型方法和可变参数 106 | public static void out(T... args) { 107 | for (T t : args) { 108 | System.out.println(t); 109 | } 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/Introspector.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5; 2 | 3 | //内省机制 4 | /*是 Java语言对Bean类属性、事件的一种缺省处理方法。 5 | 例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新 的值。 6 | 通过getName/setName来访问name属性,这就是默认的规则。 7 | Java中提供了一套API用来访问某个属性的getter /setter方法, 8 | 通过这些API可以使你不需要了解这个规则(但你最好还是要搞清楚),这些API存放于包java.beans中。 9 | 一 般的做法是通过类Introspector来获取某个对象的BeanInfo信息, 10 | 然后通过BeanInfo来获取属性的描述器 (PropertyDescriptor), 11 | 通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来 调用这些方法。*/ 12 | public class Introspector { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/PrintABCTest.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.Semaphore; 6 | 7 | public class PrintABCTest { 8 | static Semaphore A = new Semaphore(0); 9 | static Semaphore B = new Semaphore(0); 10 | static Semaphore C = new Semaphore(0); 11 | public static void main(String[] args) { 12 | 13 | ExecutorService executorService = Executors.newFixedThreadPool(10); 14 | A.release(); 15 | for(int i = 0 ; i < 10; i ++) { 16 | executorService.execute(new SayA()); 17 | executorService.execute(new SayB()); 18 | executorService.execute(new SayC()); 19 | } 20 | 21 | executorService.shutdown(); 22 | } 23 | 24 | static class SayA implements Runnable { 25 | @Override 26 | public void run() { 27 | try { 28 | A.acquire(); 29 | System.out.println("A"+Thread.currentThread()); 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | }finally { 33 | B.release(); 34 | } 35 | } 36 | } 37 | 38 | static class SayB implements Runnable { 39 | @Override 40 | public void run() { 41 | try { 42 | B.acquire(); 43 | System.out.println("B"+Thread.currentThread()); 44 | } catch (InterruptedException e) { 45 | e.printStackTrace(); 46 | }finally { 47 | C.release(); 48 | } 49 | } 50 | } 51 | static class SayC implements Runnable { 52 | @Override 53 | public void run() { 54 | try { 55 | C.acquire(); 56 | System.out.println("C"+Thread.currentThread()); 57 | } catch (InterruptedException e) { 58 | e.printStackTrace(); 59 | }finally { 60 | A.release(); 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/ScannerDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5; 2 | 3 | import java.util.Scanner; 4 | 5 | //scanner类,用来获取用户的输入 6 | public class ScannerDemo { 7 | public static void main(String[] args) { 8 | next(); 9 | nextLine(); 10 | scannerDemo1(); 11 | scannerDemo2(); 12 | } 13 | 14 | // next() 与 nextLine() 区别 15 | // next(): 16 | // 1、一定要读取到有效字符后才可以结束输入。 17 | // 2、对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。 18 | // 3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。不能得到带有空格的字符串。 19 | // nextLine(): 20 | // 1、以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。 21 | // 2、可以获得空白。 22 | 23 | public static void next() { 24 | Scanner scan = new Scanner(System.in); 25 | // 从键盘接收数据 26 | 27 | // next方式接收字符串 28 | System.out.println("next方式接收:"); 29 | // 判断是否还有输入 30 | if (scan.hasNext()) { 31 | String str1 = scan.next(); 32 | System.out.println("输入的数据为:" + str1); 33 | } 34 | } 35 | 36 | public static void nextLine() { 37 | Scanner scan = new Scanner(System.in); 38 | // 从键盘接收数据 39 | 40 | // nextLine方式接收字符串 41 | System.out.println("nextLine方式接收:"); 42 | // 判断是否还有输入 43 | if (scan.hasNextLine()) { 44 | String str2 = scan.nextLine(); 45 | System.out.println("输入的数据为:" + str2); 46 | } 47 | } 48 | 49 | // 如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,但是在输入之前最好先使用 hasNextXxx() 50 | // 方法进行验证,再使用 nextXxx() 来读取: 51 | public static void scannerDemo1() { 52 | Scanner scan = new Scanner(System.in); 53 | // 从键盘接收数据 54 | int i = 0; 55 | float f = 0.0f; 56 | System.out.print("输入整数:"); 57 | if (scan.hasNextInt()) { 58 | // 判断输入的是否是整数 59 | i = scan.nextInt(); 60 | // 接收整数 61 | System.out.println("整数数据:" + i); 62 | } else { 63 | // 输入错误的信息 64 | System.out.println("输入的不是整数!"); 65 | } 66 | System.out.print("输入小数:"); 67 | if (scan.hasNextFloat()) { 68 | // 判断输入的是否是小数 69 | f = scan.nextFloat(); 70 | // 接收小数 71 | System.out.println("小数数据:" + f); 72 | } else { 73 | // 输入错误的信息 74 | System.out.println("输入的不是小数!"); 75 | } 76 | } 77 | 78 | // 我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果 79 | public static void scannerDemo2() { 80 | Scanner scan = new Scanner(System.in); 81 | 82 | double sum = 0; 83 | int m = 0; 84 | System.out.println("输入数字求平均,输入非数字结束!"); 85 | while (scan.hasNextDouble()) { 86 | double x = scan.nextDouble(); 87 | m = m + 1; 88 | sum = sum + x; 89 | } 90 | 91 | System.out.println(m + "个数的和为" + sum); 92 | System.out.println(m + "个数的平均值是" + (sum / m)); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/VarableParameter.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5; 2 | 3 | //可变参数 4 | /*可变参数的特点: 5 | 1、只能出现在参数列表的最后; 6 | 2、...位于变量类型和变量名之间,前后有无空格都可以; 7 | 3、调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中一数组的形式访问可变参数。*/ 8 | public class VarableParameter { 9 | public static void main(String[] args) { 10 | System.out.println(add(2)); 11 | System.out.println(add(2, 3)); 12 | System.out.println(add(2, 3, 5)); 13 | } 14 | 15 | public static int add(int x, int... args) { 16 | int sum = x; 17 | /* 18 | * 【for循环方式】 for(int i=0;i concurrentHashMap = new ConcurrentHashMap(); 9 | 10 | public static void main(String[] args) { 11 | concurrentHashMap.put("1", "111"); 12 | concurrentHashMap.get("1"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/CountDownLatchDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | 5 | /** 6 | * @author wangzhongqiu 7 | * @date 2018/2/28. 8 | */ 9 | public class CountDownLatchDemo { 10 | public static void main(String[] args) { 11 | int count = 2; 12 | CountDownLatch countDownLatch = new CountDownLatch(count); 13 | Cal cal = new Cal(countDownLatch); 14 | new Thread(cal).start(); 15 | new Thread(cal).start(); 16 | try { 17 | countDownLatch.await(); 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | System.out.println("all done"); 22 | } 23 | 24 | static class Cal implements Runnable { 25 | private CountDownLatch countDownLatch; 26 | 27 | public Cal(CountDownLatch countDownLatch) { 28 | this.countDownLatch = countDownLatch; 29 | } 30 | 31 | @Override 32 | public void run() { 33 | System.out.println("完成计算"); 34 | countDownLatch.countDown(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/CyclicBarrierDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent; 2 | 3 | import java.util.concurrent.BrokenBarrierException; 4 | import java.util.concurrent.CyclicBarrier; 5 | 6 | /* 7 | * 8 | 我们知道AQS自己维护的队列是当前等待资源的队列,AQS会在资源被释放后,依次唤醒队列中从前到后的所有节点,使他们对应的线程恢复执行。直到队列为空。 9 | 而Condition自己也维护了一个队列,该队列的作用是维护一个等待signal信号的队列,两个队列的作用是不同, 10 | 事实上,每个线程也仅仅会同时存在以上两个队列中的一个,流程是这样的: 11 | 1. 线程1调用reentrantLock.lock时,线程2、线程3、线程4获取reentrantLock失败,被加入到AQS的等待队列中,进入waiting状态 12 | 2. 线程1调用await方法,--count,【addConditionWaiter】将该线程加入到Condition的等待队列中, 13 | 3. 【fullyRelease】唤醒AQS队列中的第一个等待的线程,也就是线程2,执行LockSupport.park(this);等待获得许可,线程1进入waiting状态 14 | 4. 接下来线程2,线程3,同样方式,依次,调用reentrantLock.lock,调用await方法,加入到Condition的等待队列中,进入waiting状态,等待获得许可 15 | 5. 直到线程4将count减到0,执行trip.signalAll();把Condition的等待队列中的线程重新加入到AQS的等待队列中。 16 | 6. 线程4执行完毕,执行lock.unlock();唤醒AQS的等待队列中最先进入的线程1,线程1执行完毕,执行lock.unlock(), 17 | 7. 线程1执行完毕,执行lock.unlock(),唤醒线程2,依次线程3. 18 | 可以看到,整个协作过程是靠结点在AQS的等待队列和Condition的等待队列中来回移动实现的,Condition作为一个条件类,很好的自己维护了一个等待信号的队列, 19 | 并适时的时候将结点加入到AQS的等待队列中来实现的唤醒操作。 20 | * */ 21 | //场景分析:10个人去春游,规定达到一个地点后才能继续前行. 22 | public class CyclicBarrierDemo { 23 | public static void main(String[] args) { 24 | int num = 10; 25 | CyclicBarrier barrier = new CyclicBarrier(num, new Runnable() { 26 | @Override 27 | public void run() { 28 | System.out.println("go on together!"); 29 | } 30 | }); 31 | for (int i = 1; i <= 10; i++) { 32 | new Thread(new CyclicBarrierWorker(i, barrier)).start(); 33 | try { 34 | Thread.sleep(1000); 35 | } catch (InterruptedException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | } 40 | 41 | static class CyclicBarrierWorker implements Runnable { 42 | private int id; 43 | private CyclicBarrier barrier; 44 | 45 | public CyclicBarrierWorker(int id, final CyclicBarrier barrier) { 46 | this.id = id; 47 | this.barrier = barrier; 48 | } 49 | 50 | @Override 51 | public void run() { 52 | try { 53 | System.out.println(id + " th people wait"); 54 | barrier.await(); // 大家等待最后一个线程到达 55 | System.out.println(id + " th people go on"); 56 | } catch (InterruptedException | BrokenBarrierException e) { 57 | // TODO Auto-generated catch block 58 | e.printStackTrace(); 59 | } 60 | } 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/ExchangerDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | import java.util.concurrent.Exchanger; 7 | /* 8 | * Exchanger是双向的数据传输,2个线程在一个同步点,交换数据。先到的线程会等待第二个线程执行exchange 9 | * SynchronousQueue,是2个线程之间单向的数据传输,一个put,一个take。 10 | * */ 11 | 12 | /*jdk 1.7 版本 13 | * 多个重载的exchange方法最终都是调用的doExchange(Object item, boolean timed, long nanos)方法 14 | * doExchange方法:A线程调用exchange(object),生成封装的Node对象【Node me = new Node(item)】,获取到A线程的index。开始for循环 15 | * 第一步:如果arena[index]不为空,则和【slot=arena[index]】位置的线程B交换数据, 16 | * 交换中先获取到B线程的交换数据【Object y = slot.get()】 17 | * 然后释放slot以便其他线程可以使用【slot.compareAndSet(y, null)】 18 | * 转换成Node【Node you = (Node)y】 19 | * 把交换数据传递给B线程【you.compareAndSet(null, item)】 20 | * 唤醒B线程【LockSupport.unpark(you.waiter)】 21 | * 返回B线程获取到的待交换数据【return you.item】 22 | * 第二步:【y=slot.get()==null】说明index位置没有等待交换的线程,则把A线程放到index位置等待, 23 | * 如果【index == 0】【await(me, slot)】自旋次数减少,减到0为止【LockSupport.park(me)】 24 | * 否则,自旋等待【spinWait(me, slot)】,自旋结束前获取到了其他线程的交换数据【Object v = me.get();】返回v 25 | * 自旋次数结束,返回CANCEL 26 | * index >>>= 1。index减少一半,换位置继续执行for循环 27 | * 第三步:上面两步跳过了,跳过次数过多,增大index,重新for循环 28 | * */ 29 | 30 | /*jdk 1.8 版本 31 | * 32 | * */ 33 | public class ExchangerDemo { 34 | public static void main(String[] args) { 35 | Exchanger> exchanger = new Exchanger<>(); 36 | new Consumer(exchanger).start(); 37 | //方便调试,让consumer先执行exchange 38 | try { 39 | Thread.sleep(1000 * 5); 40 | } catch (InterruptedException e) { 41 | e.printStackTrace(); 42 | } 43 | new Producer(exchanger).start(); 44 | } 45 | 46 | static class Consumer extends Thread { 47 | List list = new ArrayList<>(); 48 | Exchanger> exchanger = null; 49 | 50 | public Consumer(Exchanger> exchanger) { 51 | super(); 52 | this.exchanger = exchanger; 53 | } 54 | 55 | @Override 56 | public void run() { 57 | for (int i = 0; i < 1; i++) { 58 | try { 59 | list = exchanger.exchange(list); 60 | } catch (InterruptedException e) { 61 | e.printStackTrace(); 62 | } 63 | System.out.print(list.get(0) + ", "); 64 | System.out.print(list.get(1) + ", "); 65 | System.out.print(list.get(2) + ", "); 66 | System.out.print(list.get(3) + ", "); 67 | System.out.println(list.get(4) + ", "); 68 | } 69 | } 70 | } 71 | 72 | static class Producer extends Thread { 73 | List list = new ArrayList<>(); 74 | Exchanger> exchanger = null; 75 | 76 | public Producer(Exchanger> exchanger) { 77 | super(); 78 | this.exchanger = exchanger; 79 | } 80 | 81 | @Override 82 | public void run() { 83 | Random rand = new Random(); 84 | for (int i = 0; i < 1; i++) { 85 | list.clear(); 86 | list.add(rand.nextInt(10000)); 87 | list.add(rand.nextInt(10000)); 88 | list.add(rand.nextInt(10000)); 89 | list.add(rand.nextInt(10000)); 90 | list.add(rand.nextInt(10000)); 91 | try { 92 | list = exchanger.exchange(list); 93 | } catch (InterruptedException e) { 94 | e.printStackTrace(); 95 | } 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/FutureTaskDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent; 2 | 3 | import java.util.Date; 4 | import java.util.concurrent.Callable; 5 | import java.util.concurrent.ExecutionException; 6 | import java.util.concurrent.FutureTask; 7 | 8 | /** 9 | * @author wangzhongqiu 10 | * @date 2018/1/18. 11 | */ 12 | public class FutureTaskDemo { 13 | public static void main(String[] args) throws InterruptedException, ExecutionException { 14 | Date begin = new Date(); 15 | Calculate calculate = new Calculate(); 16 | int c = 0; 17 | 18 | //异步计算 19 | int two = 0; 20 | CallableDemo cDemo = new CallableDemo(); 21 | cDemo.setCalculate(calculate); 22 | FutureTask fTask = new FutureTask<>(cDemo); 23 | new Thread(fTask, "有返回值的线程").start(); 24 | int one = calculate.calOne(); 25 | two = fTask.get(); 26 | 27 | //求和 28 | c = one + two; 29 | Date end = new Date(); 30 | System.out.println("计算结果:" + c); 31 | long aaa = end.getTime() - begin.getTime(); 32 | System.out.println("计算耗时:" + aaa); 33 | } 34 | 35 | static class Calculate { 36 | public int calOne() throws InterruptedException { 37 | Thread.sleep(10000); 38 | return 10; 39 | } 40 | 41 | public int calTwo() throws InterruptedException { 42 | Thread.sleep(5000); 43 | return 5; 44 | } 45 | 46 | } 47 | 48 | static class CallableDemo implements Callable { 49 | private Calculate calculate; 50 | 51 | public Calculate getCalculate() { 52 | return calculate; 53 | } 54 | 55 | public void setCalculate(Calculate calculate) { 56 | this.calculate = calculate; 57 | } 58 | 59 | @Override 60 | public Integer call() throws Exception { 61 | return calculate.calTwo(); 62 | } 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/ScheduledThreadPoolExecutorDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent; 2 | 3 | import java.util.concurrent.*; 4 | 5 | /** 6 | * ScheduledThreadPoolExecutor 调度线程池 7 | * schedule,scheduleWithFixedDelay,scheduleWithFixedRate。三个方法内部都是调用的delayedExecute方法 8 | * delayedExecute方法: 一、如果线程池shutdown,拒绝任务。二、delayedWorkQueue.add(task)。 9 | * 三、ensurePrestart(),确保至少一个线程在处理任务,即使核心线程数corePoolSize为0 10 | * ensurePrestart方法:一、如果线程数量小于coreSize,addWorker(null, true)。二、否则,如果coreSize=0,addWorker(null,false) 11 | * addWorker->runWorker->getTask->delayedWorkQueue.take(阻塞,直到延迟队列的第一个元素到达了过期时间)->运行run方法 12 | * 我们知道任务添加到队列后,工作线程会从队列获取并移除到期的元素,然后执行run方法,所以下面看看ScheduledFutureTask的run方法如何实现定时调度的 13 | * run方法:一、不是循环任务,ScheduledFutureTask.super.run()。二、是循环任务,setNextRunTime();reExecutePeriodic(outerTask); 14 | */ 15 | public class ScheduledThreadPoolExecutorDemo { 16 | static ScheduledExecutorService scheduledThreadPool = new ScheduledThreadPoolExecutor(5); 17 | 18 | public static void main(String[] args) { 19 | 20 | } 21 | 22 | // 延迟1s后开始执行,只执行一次,没有返回值 23 | static void scheduleRunable() throws InterruptedException, ExecutionException { 24 | ScheduledFuture result = scheduledThreadPool.schedule(new Runnable() { 25 | @Override 26 | public void run() { 27 | System.out.println("gh"); 28 | try { 29 | Thread.sleep(3000); 30 | } catch (InterruptedException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | }, 1000, TimeUnit.MILLISECONDS); 35 | System.out.println(result.get()); 36 | } 37 | 38 | // 延迟1s后开始执行,只执行一次,有返回值 39 | static void scheduleCaller() throws InterruptedException, ExecutionException { 40 | ScheduledFuture result = scheduledThreadPool.schedule(new Callable() { 41 | @Override 42 | public String call() throws Exception { 43 | try { 44 | Thread.sleep(3000); 45 | } catch (InterruptedException e) { 46 | e.printStackTrace(); 47 | } 48 | return "gh"; 49 | } 50 | }, 1000, TimeUnit.MILLISECONDS); 51 | // 阻塞,直到任务执行完成 52 | System.out.print(result.get()); 53 | } 54 | 55 | // 固定时间间隔执行,延迟1s后开始执行任务,任务结束和下一个任务开始之间间隔2秒 56 | static void scheduleWithFixedDelay() throws ExecutionException, InterruptedException { 57 | ScheduledFuture result = scheduledThreadPool.scheduleWithFixedDelay(new Runnable() { 58 | @Override 59 | public void run() { 60 | System.out.println(System.currentTimeMillis()); 61 | } 62 | }, 1000, 2000, TimeUnit.MILLISECONDS); 63 | // 由于是定时任务,一直不会返回 64 | result.get(); 65 | System.out.println("over"); 66 | } 67 | 68 | // 固定频率执行:延迟1s后开始执行任务,每隔两秒新执行一个任务,但是如果执行任务时间大约2s则不会并发执行后续任务将会延迟。 69 | static void scheduleAtFixedRate() throws InterruptedException, ExecutionException { 70 | ScheduledFuture result = scheduledThreadPool.scheduleAtFixedRate(new Runnable() { 71 | @Override 72 | public void run() { 73 | System.out.println(System.currentTimeMillis()); 74 | } 75 | }, 1000, 2000, TimeUnit.MILLISECONDS); 76 | // 由于是定时任务,一直不会返回 77 | result.get(); 78 | System.out.println("over"); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/SemaphoreDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.Semaphore; 6 | 7 | /* 8 | * 实现原理,和countdownlatch类似,内部类sync实现了AbstractQueuedSynchronizer 9 | * 使用场景:Semaphore经常用于限制获取某种资源的线程数量。 10 | * 比如说操场上有5个跑道,一个跑道一次只能有一个学生在上面跑步,一旦所有跑道在使用, 11 | * 那么后面的学生就需要等待,直到有一个学生不跑了 12 | * */ 13 | public class SemaphoreDemo { 14 | public static void main(String[] args) { 15 | // 线程池 16 | ExecutorService exec = Executors.newCachedThreadPool(); 17 | // 只能5个线程同时访问 18 | final Semaphore semaphore = new Semaphore(5); 19 | // 模拟20个客户端访问 20 | for (int index = 0; index < 20; index++) { 21 | final int NO = index; 22 | Runnable run = new Runnable() { 23 | 24 | public void run() { 25 | try { 26 | // 获取许可 27 | semaphore.acquire(); 28 | System.out.println("Accessing: " + NO); 29 | Thread.sleep((long) (Math.random() * 10000)); 30 | // 访问完后,释放 31 | semaphore.release(); 32 | System.out.println("-----------------" + semaphore.availablePermits()); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | }; 39 | exec.execute(run); 40 | } 41 | // 退出线程池 42 | exec.shutdown(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/AtomicBooleanDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.atomic; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | import java.util.concurrent.atomic.AtomicIntegerArray; 6 | import java.util.concurrent.atomic.AtomicLong; 7 | 8 | /** 9 | * @author wangzhongqiu 10 | * @date 2018/2/9. 11 | */ 12 | public class AtomicBooleanDemo { 13 | public static void main(String[] args) { 14 | AtomicBoolean atomicBoolean = new AtomicBoolean(); 15 | atomicBoolean.getAndSet(true); 16 | 17 | AtomicLong atomicLong = new AtomicLong(); 18 | atomicLong.getAndDecrement(); 19 | 20 | AtomicInteger atomicInteger = new AtomicInteger(); 21 | atomicInteger.incrementAndGet(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/AtomicIntegerArrayDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.atomic; 2 | 3 | import javafx.beans.binding.ObjectExpression; 4 | 5 | import java.util.concurrent.atomic.AtomicIntegerArray; 6 | import java.util.concurrent.atomic.AtomicLongArray; 7 | import java.util.concurrent.atomic.AtomicReferenceArray; 8 | 9 | /** 10 | * @author wangzhongqiu 11 | * @date 2018/2/9. 12 | */ 13 | public class AtomicIntegerArrayDemo { 14 | public volatile int[] a = {1, 2}; 15 | 16 | public static void main(String[] args) { 17 | System.out.println(31 - Integer.numberOfLeadingZeros(8)); 18 | System.out.println(32 - Integer.numberOfLeadingZeros(8 - 1)); 19 | int[] array = {1, 2, 3, 4}; 20 | long[] longArray = {1, 2, 3, 4}; 21 | AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(array); 22 | atomicIntegerArray.getAndIncrement(1); 23 | 24 | AtomicLongArray atomicLongArray = new AtomicLongArray(longArray); 25 | atomicLongArray.getAndIncrement(1); 26 | 27 | Object[] objects = {new Object(), new Object()}; 28 | AtomicReferenceArray atomicReferenceArray = new AtomicReferenceArray(objects); 29 | atomicReferenceArray.compareAndSet(1, new Object(), new Object()); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/AtomicIntegerDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.atomic; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | //这是由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快 6 | public class AtomicIntegerDemo { 7 | public static void main(String[] args) { 8 | final Counter counter = new Counter(); 9 | final CounterSyn counterSyn = new CounterSyn(); 10 | final CounterAtomic counterAtomic = new CounterAtomic(); 11 | 12 | for (int i = 0; i < 3; i++) { 13 | new Thread(new Runnable() { 14 | @Override 15 | public void run() { 16 | for (int j = 0; j < 1000; j++) { 17 | try { 18 | Thread.sleep(5); 19 | } catch (InterruptedException e) { 20 | e.printStackTrace(); 21 | } 22 | // counterSyn.increment(); 23 | // counterAtomic.increment(); 24 | counter.increment(); 25 | } 26 | } 27 | }).start(); 28 | } 29 | try { 30 | Thread.sleep(1000 * 10); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | System.out.println("counter:" + counter.getCount()); 35 | System.out.println("counterSyn:" + counterSyn.getCount()); 36 | System.out.println("counterAtomic:" + counterAtomic.getCount()); 37 | } 38 | 39 | static class Counter implements Count { 40 | private volatile int count = 0; 41 | 42 | @Override 43 | public void increment() { 44 | count++; 45 | } 46 | 47 | @Override 48 | public int getCount() { 49 | return count; 50 | } 51 | } 52 | 53 | static class CounterSyn implements Count { 54 | private volatile int count = 0; 55 | 56 | // 若要线程安全执行执行count++,需要加锁 57 | @Override 58 | public synchronized void increment() { 59 | try { 60 | Thread.sleep(1000 * 20); 61 | } catch (InterruptedException e) { 62 | e.printStackTrace(); 63 | } 64 | count++; 65 | } 66 | 67 | @Override 68 | public int getCount() { 69 | return count; 70 | } 71 | } 72 | 73 | static class CounterAtomic implements Count { 74 | private AtomicInteger count = new AtomicInteger(); 75 | 76 | @Override 77 | public void increment() { 78 | count.incrementAndGet(); 79 | } 80 | 81 | @Override 82 | public int getCount() { 83 | return count.get(); 84 | } 85 | } 86 | 87 | interface Count { 88 | void increment(); 89 | 90 | int getCount(); 91 | } 92 | 93 | static class Add implements Runnable { 94 | public Count getCount() { 95 | return count; 96 | } 97 | 98 | public void setCount(Count count) { 99 | this.count = count; 100 | } 101 | 102 | private Count count; 103 | 104 | Add(Count count) { 105 | this.count = count; 106 | } 107 | 108 | @Override 109 | public void run() { 110 | count.increment(); 111 | } 112 | } 113 | } 114 | 115 | 116 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/AtomicIntegerFieldUpdaterDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.atomic; 2 | 3 | import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; 4 | import java.util.concurrent.atomic.AtomicLongFieldUpdater; 5 | import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; 6 | 7 | /** 8 | * @author wangzhongqiu 9 | * @date 2018/2/11. 10 | */ 11 | public class AtomicIntegerFieldUpdaterDemo { 12 | public static void main(String[] args) { 13 | Person person = new Person("zhangsan", 11, 170); 14 | person.setHobby(new Hobby("打球", "足球,篮球")); 15 | AtomicIntegerFieldUpdater atomicIntegerFieldUpdater = AtomicIntegerFieldUpdater.newUpdater(Person.class, "age"); 16 | atomicIntegerFieldUpdater.addAndGet(person, 12); 17 | 18 | AtomicLongFieldUpdater atomicLongFieldUpdater = AtomicLongFieldUpdater.newUpdater(Person.class, "height"); 19 | atomicLongFieldUpdater.addAndGet(person, 180); 20 | 21 | AtomicReferenceFieldUpdater atomicReferenceFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(Person.class, Hobby.class, "hobby"); 22 | atomicReferenceFieldUpdater.getAndSet(person, new Hobby("打球", "排球,羽毛球")); 23 | 24 | } 25 | 26 | static class Person { 27 | private String name; 28 | private int age; 29 | private long height; 30 | 31 | private Hobby hobby; 32 | 33 | public Person(String name, int age, long height) { 34 | this.name = name; 35 | this.age = age; 36 | this.height = height; 37 | } 38 | 39 | public String getName() { 40 | return name; 41 | } 42 | 43 | public void setName(String name) { 44 | this.name = name; 45 | } 46 | 47 | public int getAge() { 48 | return age; 49 | } 50 | 51 | public void setAge(int age) { 52 | this.age = age; 53 | } 54 | 55 | public long getHeight() { 56 | return height; 57 | } 58 | 59 | public void setHeight(long height) { 60 | this.height = height; 61 | } 62 | 63 | public Hobby getHobby() { 64 | return hobby; 65 | } 66 | 67 | public void setHobby(Hobby hobby) { 68 | this.hobby = hobby; 69 | } 70 | 71 | @Override 72 | public String toString() { 73 | return "[name: " + this.name + ", age: " + this.age + "]"; 74 | } 75 | } 76 | 77 | static class Hobby { 78 | private String hobbyName; 79 | 80 | private String info; 81 | 82 | public Hobby(String hobbyName, String info) { 83 | this.hobbyName = hobbyName; 84 | this.info = info; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/AtomicMarkableReferenceDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.atomic; 2 | 3 | import java.util.concurrent.atomic.AtomicMarkableReference; 4 | 5 | /** 6 | * @author wangzhongqiu 7 | * @date 2018/2/27. 8 | */ 9 | public class AtomicMarkableReferenceDemo { 10 | public static void main(String[] args) { 11 | Integer a = 1; 12 | AtomicMarkableReference atomicMarkableReference = new AtomicMarkableReference(a, false); 13 | atomicMarkableReference.compareAndSet(1, 2, false, true); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/AtomicReferenceDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.atomic; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | 5 | /** 6 | * @author wangzhongqiu 7 | * @date 2018/2/11. 8 | */ 9 | public class AtomicReferenceDemo { 10 | public static void main(String[] args) { 11 | Person person = new Person("zhangsan", 11); 12 | AtomicReference atomicReference = new AtomicReference<>(person); 13 | atomicReference.getAndSet(new Person("zhangsan", 12)); 14 | } 15 | 16 | static class Person { 17 | private String name; 18 | private int age; 19 | 20 | public Person(String name, int age) { 21 | this.name = name; 22 | this.age = age; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | public void setName(String name) { 30 | this.name = name; 31 | } 32 | 33 | public int getAge() { 34 | return age; 35 | } 36 | 37 | public void setAge(int age) { 38 | this.age = age; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "[name: " + this.name + ", age: " + this.age + "]"; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/AtomicStampedReferenceDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.atomic; 2 | 3 | import java.util.concurrent.atomic.AtomicStampedReference; 4 | 5 | /** 6 | * @author wangzhongqiu 7 | * @date 2018/2/26. 8 | */ 9 | public class AtomicStampedReferenceDemo { 10 | static AtomicStampedReference atomicStampedReference = new AtomicStampedReference(0, 0); 11 | 12 | public static void main(String[] args) throws InterruptedException { 13 | final int stamp = atomicStampedReference.getStamp(); 14 | final Integer reference = atomicStampedReference.getReference(); 15 | System.out.println(reference + "============" + stamp); 16 | Thread t1 = new Thread(new Runnable() { 17 | @Override 18 | public void run() { 19 | System.out.println(reference + "-" + stamp + "-" 20 | + atomicStampedReference.compareAndSet(reference, reference + 10, stamp, stamp + 1)); 21 | } 22 | }); 23 | 24 | Thread t2 = new Thread(new Runnable() { 25 | @Override 26 | public void run() { 27 | Integer reference = atomicStampedReference.getReference(); 28 | System.out.println(reference + "-" + stamp + "-" 29 | + atomicStampedReference.compareAndSet(reference, reference + 10, stamp, stamp + 1)); 30 | } 31 | }); 32 | t1.start(); 33 | t1.join(); 34 | t2.start(); 35 | t2.join(); 36 | 37 | System.out.println(atomicStampedReference.getReference()); 38 | System.out.println(atomicStampedReference.getStamp()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/atomic/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @author wangzhongqiu 3 | * 在非激烈竞争的情况下,开销更小,速度更快 4 | * 5 | */ 6 | package zhongqiu.common.jdk5.concurrent.atomic; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/locks/LockSupportDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.locks; 2 | 3 | import java.util.concurrent.locks.LockSupport; 4 | 5 | /** 6 | * @author wangzhongqiu 7 | * @date 2018/2/1. 8 | */ 9 | public class LockSupportDemo { 10 | public static void main(String[] args) { 11 | SpinRunnable spinRunnable = new SpinRunnable(); 12 | Thread thread = new Thread(spinRunnable, "new"); 13 | thread.start(); 14 | try { 15 | Thread.sleep(1000 * 3); 16 | } catch (InterruptedException e) { 17 | e.printStackTrace(); 18 | } 19 | System.out.println("thread线程状态:" + thread.getState()); 20 | 21 | LockSupport.unpark(thread); 22 | try { 23 | Thread.sleep(1000 * 3); 24 | } catch (InterruptedException e) { 25 | e.printStackTrace(); 26 | } 27 | System.out.println("thread线程状态:" + thread.getState()); 28 | 29 | LockSupport.unpark(thread); 30 | LockSupport.unpark(thread); 31 | LockSupport.unpark(thread); 32 | System.out.println("thread线程状态:" + thread.getState()); 33 | } 34 | 35 | //阻塞thread 36 | public static class BlockRunnable implements Runnable { 37 | private volatile int count = 50; 38 | private static Object lock = new Object(); 39 | 40 | @Override 41 | public void run() { 42 | System.out.println("thread线程开始运行"); 43 | synchronized (lock) { 44 | try { 45 | lock.wait(1000 * 10); 46 | } catch (InterruptedException e) { 47 | System.out.println("thread线程状态:" + Thread.currentThread().getState()); 48 | } 49 | } 50 | System.out.println("thread线程运行结束"); 51 | } 52 | } 53 | 54 | //自旋thread 55 | public static class SpinRunnable implements Runnable { 56 | private volatile int count = 50; 57 | private static Object lock = new Object(); 58 | 59 | @Override 60 | public void run() { 61 | System.out.println("thread线程开始运行"); 62 | LockSupport.park(); 63 | 64 | while (true) { 65 | 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/locks/ReentrantLockDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.locks; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | /* 6 | * 1. Lock的加锁和解锁都是由java代码配合native方法(调用操作系统的相关方法)实现的,而synchronize的加锁和解锁的过程是由JVM管理的 7 | * 2. 当一个线程使用synchronize获取锁时,若锁被其他线程占用着,那么当前只能被阻塞,直到成功获取锁。 8 | * 而Lock则提供超时锁和可中断等更加灵活的方式,在未能获取锁的条件下提供一种退出的机制。 9 | * 3. 一个锁内部可以有多个Condition实例,即有多路条件队列,而synchronize只有一路条件队列; 10 | * 同样Condition也提供灵活的阻塞方式,在未获得通知之前可以通过中断线程以及设置等待时限等方式退出条件队列。 11 | * 4. synchronize对线程的同步仅提供独占模式,而Lock即可以提供独占模式,也可以提供共享模式 12 | * */ 13 | public class ReentrantLockDemo { 14 | public static void main(String[] args) { 15 | final Outputter1 output = new Outputter1(); 16 | // new Thread() { 17 | // public void run() { 18 | // output.output("zhangsan"); 19 | // } 20 | // 21 | // ; 22 | // }.start(); 23 | new Thread() { 24 | @Override 25 | public void run() { 26 | output.output("lisi"); 27 | } 28 | 29 | ; 30 | }.start(); 31 | } 32 | 33 | static class Outputter1 { 34 | private ReentrantLock nonfairLock = new ReentrantLock(); 35 | private ReentrantLock fairLock = new ReentrantLock(true); 36 | 37 | public void output(String name) { 38 | nonfairLock.lock(); 39 | fairLock.lock(); 40 | try { 41 | for (int i = 0; i < name.length(); i++) { 42 | System.out.print(name.charAt(i)); 43 | } 44 | } finally { 45 | nonfairLock.unlock(); 46 | fairLock.unlock(); 47 | } 48 | } 49 | } 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/locks/ReentrantReadWriteLockDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.concurrent.locks; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.locks.ReentrantReadWriteLock; 5 | 6 | /*读写锁 7 | * 1.读锁,很多人同时读,但不能同时写;写锁,只能有一个人在写,且不能同时读取 8 | * */ 9 | public class ReentrantReadWriteLockDemo { 10 | public static void main(String[] args) { 11 | final Queue3 q3 = new Queue3(); 12 | for (int i = 0; i < 3; i++) { 13 | new Thread() { 14 | @Override 15 | public void run() { 16 | while (true) { 17 | q3.get(); 18 | } 19 | } 20 | 21 | }.start(); 22 | } 23 | for (int i = 0; i < 3; i++) { 24 | new Thread() { 25 | public void run() { 26 | while (true) { 27 | q3.put(new Random().nextInt(10000)); 28 | } 29 | } 30 | 31 | }.start(); 32 | } 33 | } 34 | 35 | static class Queue3 { 36 | private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。 37 | private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 38 | public void get() { 39 | rwl.readLock().lock();//上读锁,其他线程只能读不能写 40 | System.out.println(Thread.currentThread().getName() + " be ready to read data!"); 41 | try { 42 | Thread.sleep((long) (Math.random() * 1000)); 43 | } catch (InterruptedException e) { 44 | e.printStackTrace(); 45 | } 46 | System.out.println(Thread.currentThread().getName() + "have read data :" + data); 47 | rwl.readLock().unlock(); //释放读锁,最好放在finnaly里面 48 | } 49 | 50 | public void put(Object data) { 51 | 52 | rwl.writeLock().lock();//上写锁,不允许其他线程读也不允许写 53 | System.out.println(Thread.currentThread().getName() + " be ready to write data!"); 54 | try { 55 | Thread.sleep((long) (Math.random() * 1000)); 56 | } catch (InterruptedException e) { 57 | e.printStackTrace(); 58 | } 59 | this.data = data; 60 | System.out.println(Thread.currentThread().getName() + " have write data: " + data); 61 | 62 | rwl.writeLock().unlock();//释放写锁 63 | } 64 | } 65 | } 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/locks/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @author wangzhongqiu 3 | * (0)Java无法直接访问底层操作系统,而是通过本地(native)方法来访问。 4 | * 不过尽管如此,JVM还是开了一个后门,JDK中有一个类Unsafe,它提供了硬件级别的原子操作。 5 | * 当前的处理器基本都支持CAS,只不过不同的厂家的实现不一样罢了。 6 | * unsafe.compareAndSwapInt(this, stateOffset, expect, update)。 7 | * 【说明】CAS原语可以用来实现无锁的数据结构。是CPU指令级的操作,只有一步原子操作 8 | * 【步骤】有一些状态,创建它的副本,修改它,执行CAS,如果失败,重复尝试 9 | * 【存在问题】如ABA问题、指令重排序等。 10 | * (0)LockSupport 11 | * park():当前线程进入Waiting状态,等待许可 12 | * unpark(thread):给thread线程一个许可 13 | * (1)可重入独占锁。ReentrantLock的锁资源以state状态描述,利用CAS则实现对锁资源的抢占,并通过一个FIFO队列阻塞所有竞争线程, 14 | * 在后续则逐个唤醒等待中的竞争线程。ReentrantLock继承AQS完全从代码层面实现了java的同步机制, 15 | * 相对于synchronized,更容易实现对各类锁的扩展。同时,AbstractQueuedSynchronizer中的Condition配合ReentrantLock使用, 16 | * 实现了wait/notify的功能。 17 | * ReentrantLock implements Lock。成员变量:Sync sync; 18 | * 【Sync extends AbstractQueuedSynchronizer】实现了CLH锁算法,CLH锁是一个自旋锁,能确保无饥饿性,提供先来先服务的公平性。 19 | * 【AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer】 20 | * 成员变量:long stateOffset;int state;Node tail;Node head;内部类Node(waitStatus,prev,next,thread,nextWaiter锁类型); 21 | * 【AbstractOwnableSynchronizer】成员变量:Thread exclusiveOwnerThread; 22 | * 【NonfairSync extends Sync】非公平锁:当锁处于无线程占有的状态,此时其他线程和在队列中等待的线程都可以抢占该锁。 23 | * 【FairSync extends Sync】公平锁:当锁处于无线程占有的状态,在其他线程抢占该锁的时候,都需要先进入队列中等待。 24 | * 【非公平锁 lock方法】 25 | * 所有线程先执行一遍cas竞争锁,if compareAndSetState(0, 1);setExclusiveOwnerThread(Thread.currentThread()); 26 | * CAS失败,执行带有阻塞队列FIFO的acquire(1)方法 27 | * cas竞争锁:判断state等于0,cas竞争锁,setExclusiveOwnerThread;不为零且当前线程是持有锁的线程,state+1; 28 | * 竞争锁失败,放入队列中继续尝试获得锁acquireQueued(addWaiter(Node.EXCLUSIVE), arg)); 29 | * 自旋入队列addWaiter,tail不为空,node放入队尾;tail为空,自旋for循环直到初始化并且放入队尾成功。compareAndSetHead,compareAndSetTail 30 | * acquireQueued。for无限循环。自旋在阻塞队列中竞争锁 31 | * 判断node节点的pre节点是否为头结点,是则node去竞争锁,获取到锁,把node置成头结点,return interrupted(初始为false) 32 | * 没有获取到锁或者不是头结点则执行方法【shouldParkAfterFailedAcquire】:判断node前节点的waitStatus是否为-1(等待锁状态), 33 | * 是则返回true。调用LockSupport.park(this)阻塞等待许可,获取许可,更新interrupted的值为Thread.interrupted(),重新下一次for循环 34 | * 不是且waitStatus>0,则从阻塞队列中移除状态为1(取消等待锁)的pre节点,返回false,重新下一次for循环 35 | * 如果acquireQueued方法返回true,执行 Thread.currentThread().interrupt(); 36 | * 【公平锁 lock方法】 37 | * 【lock()】->【acquire(1)】->【if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))】-> 38 | * 【if (c == 0) { 39 | if (!hasQueuedPredecessors() && 40 | compareAndSetState(0, acquires)) { 41 | setExclusiveOwnerThread(current); 42 | return true; 43 | } 44 | }】 45 | * 【unlock方法】 46 | * tryRelease(1)->state减小,如果减小到了0,则setExclusiveOwnerThread(null); 47 | * unparkSuccessor(h),如果头结点的next节点不为空,LockSupport.unpark(s.thread) 48 | * 如果next节点为空或者waitStatus > 0,从tail往前遍历到离head最近的waitStatus <= 0的节点,LockSupport.unpark(s.thread) 49 | * (2)读写锁 ReentrantReadWriteLock【参考文章:http://www.cnblogs.com/wangzhongqiu/p/8422925.html】 50 | * 【readLock().lock()】->【acquireShared(int arg)】->【if (tryAcquireShared(arg) < 0)】->【doAcquireShared(arg)】 51 | * 【tryAcquireShared没有阻塞方法,没有自旋。判断有写锁,失败。读写达到最大值,失败,阻塞队列中还有node,失败。竞争锁】 52 | * 【tryAcquireShared失败,doAcquireShared 入阻塞队列,前节点为头结点竞争锁,失败park等待】【CLH锁,FIFO队列】 53 | * 【readLock().unlock()】->【releaseShared(int arg)】->【if (tryReleaseShared(arg))】->【doReleaseShared()】 54 | * 【tryReleaseShared 自旋释放锁直到成功,return nextc == 0;】 55 | * 【doReleaseShared 自旋直到把队列中第一个阻塞的线程唤醒】 56 | * 如果next节点为空或者waitStatus > 0,从tail往前遍历到离head最近的waitStatus <= 0的节点,LockSupport.unpark(s.thread) 57 | * 【writeLock().lock()】-> 58 | * 【acquire(1)】 59 | * if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 60 | selfInterrupt(); 61 | * 【tryAcquire(1) 已经有读锁,失败;已经有写锁了,累加state;读锁和写锁都没有,CAS竞争锁(公平锁还要在竞争锁之前判断是否有线程已经在wait)】 62 | * 【writeLock().unlock()】->【release(1)】->【tryRelease(1)】->【unparkSuccessor(h)】 63 | * 【tryRelease(1)】自旋释放锁直到成功,return nextc == 0; 64 | * 【unparkSuccessor(h)】自旋直到把队列中第一个阻塞的线程唤醒 return exclusiveCount(nextc) == 0 65 | */ 66 | package zhongqiu.common.jdk5.concurrent.locks; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/concurrent/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @author zhongqiu 3 | * jdk5,并发新特性。JUC http://ifeve.com/doug-lea/ 4 | * (1) locks:LockSupport,ReentrantLock,ReentrantReadWriteLock 5 | * (2) atomic:原子更新基本类型(AtomicBoolean,AtomicInteger,AtomicLong)、 6 | * 原子更新数组(AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray)、 7 | * 原子更新引用(AtomicReference)、 8 | * 原子更新属性(AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater) 9 | * AtomicReferenceFieldUpdater的使用有以下限制: 10 | * 字段必须是volatile类型的,在线程之间共享变量时保证立即可见 11 | * 只能是实例变量,不能是类变量,也就是说不能加static关键字 12 | * 只能是可修改变量,不能使final变量,因为final的语义就是不可修改。 13 | * 对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。 14 | * 如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。 15 | * 解决ABA问题(AtomicMarkableReference,AtomicStampedReference) 16 | * (3) ConcurrentHashMap.持有对象:Segment[] segments;segmentMask;segmentShift 17 | * 【Segment extends ReentrantLock】HashEntry[] table;modCount;threshold;count;loadFactor 18 | * 【HashEntry】final hash;final key;value;HashEntry next; 19 | * (4) CountDownLatch 20 | * (5) CyclicBarrier 21 | * (6) Semaphore 22 | * (7) BlockingQueue:ArrayBlockingQueue,LinkedBlockingQueue,SynchronousQueue,PriorityBlockingQueue,DelayQueue 23 | * (9) Exchanger 24 | * (8) ThreadPoolExecutor 25 | * (9) Executors 26 | * (9) ScheduledThreadPoolExecutor 27 | * (9) 28 | */ 29 | package zhongqiu.common.jdk5.concurrent; 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * @author zhongqiu 3 | * jdk5特性 4 | * 主要特性: 5 | * (1)自动装箱与拆箱 6 | * (2)枚举:枚举的switch,自定义枚举,枚举实现接口 7 | * (3)静态导入:import static java.lang.System.out;静态导入的是静态方法 8 | * (4)可变参数(Varargs): int ... args 9 | * (5)内省(Introspector) 10 | * (6)泛型:泛型类;泛型作为参数和可变参数;泛型作为返回值;泛型方法;类型通配符和extend和super用法; 11 | * (7)增强型for循环For-Each 12 | * (8)Scanner类。用来获取用户的输入 13 | * (9)线程相关类。 14 | * (9)队列:【阻塞队列】blockingqueue(add、put和take,offer和poll,contains,remove,drainTo) 15 | * ArrayBlockingQueue,LinkedBlockingQueue,,PriorityBlockingQueue 16 | * DelayQueue:重写getDelay和compareTo方法 17 | * SynchronousQueue:每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然。同步队列没有任何内部容量,甚至连一个队列的容量都没有。 18 | * 【优先级队列】PriorityQueue 19 | * (10)CountDownLatch。同步辅助类(await,countDown,getCount)。 20 | * 应用场景:假如有Thread1、Thread2、Thread3、Thread4四条线程分别统计C、D、E、F四个盘的大小,所有线程都统计完毕交给Thread5线程去做汇总 21 | * CyclicBarrier。同步辅助类,栅栏。barrier.await(); 22 | * Semaphore。计数信号量。semp.acquire();semp.release(); 23 | * Exchanger。可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据 24 | * (11)ConcurrentHashMap。应用场景,实现原理,锁分离技术,volatile,Segment,和hashtable的区别,弱一致迭代器,读不需要锁 25 | * (12)ReentrantLock。在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock, 26 | * 但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍 27 | * 公平锁(new RenentrantLock(boolean fair)),synchronized默认公平锁,ReentrantLock默认不公平锁 28 | * 定时锁等候(tryLock)和可中断锁等候. lock 必须在 finally 块中释放 29 | * (13)ReentrantReadWriteLock。读写锁。和synchronized的区别。实现原理的不同, 30 | * (14)Atomic。原子性操作。addAndGet和getAndAdd和decrementAndGet() ,compareAndSet(int expect, int update) 31 | * (15)线程池Executors。ExecutorService exec = Executors.newCachedThreadPool(); 32 | * pool.execute(new RunnableTest("Task2")); 33 | * Future future = pool.submit(new RunnableTest("Task2"));有返回值 34 | * newCachedThreadPool();newFixedThreadPool(3);newSingleThreadExecutor();newScheduledThreadPool(5) 35 | * 36 | */ 37 | package zhongqiu.common.jdk5; 38 | 39 | import java.util.concurrent.ExecutorService; 40 | import java.util.concurrent.Executors; 41 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk5/util/PriorityQueueDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk5.util; 2 | 3 | import java.util.Comparator; 4 | import java.util.PriorityQueue; 5 | import java.util.Queue; 6 | 7 | public class PriorityQueueDemo { 8 | private String name; 9 | private int population; 10 | 11 | public PriorityQueueDemo(String name, int population) { 12 | this.name = name; 13 | this.population = population; 14 | } 15 | 16 | public String getName() { 17 | return this.name; 18 | } 19 | 20 | public int getPopulation() { 21 | return this.population; 22 | } 23 | 24 | public String toString() { 25 | return getName() + " - " + getPopulation(); 26 | } 27 | 28 | public static void main(String args[]) { 29 | // 和 Comparable 的对比 30 | Comparator OrderIsdn = new Comparator() { 31 | public int compare(PriorityQueueDemo o1, PriorityQueueDemo o2) { 32 | // TODO Auto-generated method stub 33 | int numbera = o1.getPopulation(); 34 | int numberb = o2.getPopulation(); 35 | if (numberb > numbera) { 36 | return 1; 37 | } else if (numberb < numbera) { 38 | return -1; 39 | } else { 40 | return 0; 41 | } 42 | 43 | } 44 | 45 | }; 46 | Queue priorityQueue = new PriorityQueue(11, OrderIsdn); 47 | 48 | PriorityQueueDemo t1 = new PriorityQueueDemo("t1", 1); 49 | PriorityQueueDemo t3 = new PriorityQueueDemo("t3", 3); 50 | PriorityQueueDemo t2 = new PriorityQueueDemo("t2", 2); 51 | PriorityQueueDemo t4 = new PriorityQueueDemo("t4", 0); 52 | priorityQueue.add(t1); 53 | priorityQueue.add(t3); 54 | priorityQueue.add(t2); 55 | priorityQueue.add(t4); 56 | System.out.println(priorityQueue.poll().toString()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk6/AnnotationDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk6; 2 | 3 | //插入式注解处理api 4 | public class AnnotationDemo { 5 | /* 6 | * 插入式注解处理API(JSR 269)提供一套标准API来处理Annotations.JSR 269用Annotation 7 | * Processor【在编译期间而不是运行期间处理】Annotation, Annotation Processor相当于编译器的一个插件, 8 | * 9 | * 所以称为插入式注解处理.如果Annotation 10 | * Processor处理Annotation时(执行process方法)产生了新的Java代码,编译器会再调用一次Annotation 11 | * Processor,如果第二次处理还有新代码产生,就会接着调用Annotation 12 | * Processor,直到没有新代码产生为止.每执行一次process()方法被称为一个"round",这样整个Annotation 13 | * processing过程可以看作是一个round的序列. 14 | * 举个例子:们想建立一套基于Annotation的单元测试框架(如TestNG),在测试类里面用Annotation来标识测试期间需要执行的测试方法 15 | */ 16 | public @interface TestMethod { 17 | 18 | } 19 | @TestMethod 20 | public void testCheckName(){ 21 | //do something here 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk6/CompilerAPIDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk6; 2 | 3 | /*在我们可以用JDK6 的Compiler API(JSR 199)去动态编译Java源文件, 4 | Compiler API结合反射功能就可以实现动态的产生Java代码并编译执行这些代码,有点动态语言的特征。 5 | 这个特性对于某些需要用到动态编译的应用程序相当有用,比如JSP Web Server, 6 | 当我们手动修改JSP后,是不希望需要重启Web Server才可以看到效果的, 7 | 这时候我们就可以用Compiler API来实现动态编译JSP文件,当然,现在的JSP Web Server也是支持JSP热部署的, 8 | 现在的JSP Web Server通过在运行期间通过Runtime.exec或ProcessBuilder来调用javac来编译代码, 9 | 这种方式需要我们产生另一个进程去做编译工作,不够优雅而且容易使代码依赖与特定的操作系统; 10 | Compiler API通过一套易用的标准的API提供了更加丰富的方式去做动态编译,而且是跨平台的。*/ 11 | public class CompilerAPIDemo { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk6/ConsoleDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk6; 2 | 3 | import java.io.Console; 4 | 5 | //用Console开发控制台程序 6 | /*你如果是在一个IDE中如eclipse, netbeans中运行你将得到: 7 | No Console! 8 | 因为只有在命令行中才能得到Console对象。*/ 9 | public class ConsoleDemo { 10 | public static void main(String[] args) { 11 | Console console = System.console(); 12 | if (console != null) { 13 | String user = new String(console.readLine("Enter User:", new Object[0])); 14 | String pwd = new String(console.readPassword("Enter Password:", new Object[0])); 15 | console.printf("User name is:%s", new Object[] { user }); 16 | console.printf("Password is:%s", new Object[] { pwd }); 17 | } else { 18 | System.out.println("No Console!"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk6/HttpServerAPIDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk6; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | // import com.sun.net.httpserver.HttpExchange; 7 | // import com.sun.net.httpserver.HttpHandler; 8 | // import com.sun.net.httpserver.HttpServer; 9 | // 10 | // public class HttpServerAPIDemo { 11 | // private static int count = 0; 12 | // 13 | // public static void main(String[] args) { 14 | // try { 15 | // HttpServer hs = HttpServer.create(new InetSocketAddress(8888), 0); 16 | // hs.createContext("/", new MyHandler()); 17 | // hs.createContext("/java", new MyHandler()); 18 | // hs.setExecutor(null); 19 | // hs.start(); 20 | // System.out.println("---begin---"); 21 | // System.out.println("Listening on " + hs.getAddress()); 22 | // } catch (IOException ioe) { 23 | // ioe.printStackTrace(); 24 | // } 25 | // } 26 | // 27 | // static class MyHandler implements HttpHandler { 28 | // public void handle(HttpExchange he) throws IOException { 29 | // System.out.println("Request " + count++); 30 | // System.out.println(he.getHttpContext().getPath()); 31 | // 32 | // InputStream is = he.getRequestBody(); 33 | // String response = "Happy Spring Festerval"; 34 | // he.sendResponseHeaders(200, response.length()); 35 | // OutputStream os = he.getResponseBody(); 36 | // os.write(response.getBytes()); 37 | // os.close(); 38 | // } 39 | // } 40 | // } 41 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk6/ScriptDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk6; 2 | 3 | import java.io.FileReader; 4 | 5 | import javax.script.Invocable; 6 | import javax.script.ScriptEngine; 7 | import javax.script.ScriptEngineManager; 8 | 9 | //对脚本语言的支持:script 10 | public class ScriptDemo { 11 | public static void main(String[] args) { 12 | ScriptEngineManager manager = new ScriptEngineManager(); 13 | ScriptEngine engine = manager.getEngineByName("ECMAScript"); 14 | try { 15 | engine.eval(new FileReader("D://test.js")); 16 | Invocable invocableEngine = (Invocable) engine; 17 | Object ret = invocableEngine.invokeFunction("test", null); 18 | System.out.println("The result is :" + (Double) ret); 19 | } catch (Exception e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk6/StaxDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk6; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileOutputStream; 6 | 7 | import javax.xml.namespace.QName; 8 | import javax.xml.stream.XMLEventReader; 9 | import javax.xml.stream.XMLInputFactory; 10 | import javax.xml.stream.XMLOutputFactory; 11 | import javax.xml.stream.XMLStreamException; 12 | import javax.xml.stream.XMLStreamWriter; 13 | import javax.xml.stream.events.StartElement; 14 | import javax.xml.stream.events.XMLEvent; 15 | 16 | //STAX处理xml 17 | public class StaxDemo { 18 | public static void main(String[] arg) throws XMLStreamException, FileNotFoundException { 19 | readXMLByStAX(); 20 | writeXMLByStAX(); 21 | } 22 | 23 | public static void readXMLByStAX() throws XMLStreamException, FileNotFoundException { 24 | XMLInputFactory factory = XMLInputFactory.newInstance(); 25 | XMLEventReader reader = factory.createXMLEventReader(new FileInputStream("test.xml"));//StaxDemo.class.getResourceAsStream("test.xml") 26 | XMLEvent event; 27 | StringBuffer parsingResult = new StringBuffer(); 28 | while (reader.hasNext()) { 29 | event = reader.nextEvent(); 30 | if (event.isStartElement()) { 31 | StartElement se = event.asStartElement(); 32 | parsingResult.append("<"); 33 | parsingResult.append(se.getName()); 34 | if (se.getName().getLocalPart().equals("catalog")) { 35 | parsingResult.append("id="); 36 | parsingResult.append(se.getAttributeByName(new QName("id")).getValue()); 37 | parsingResult.append(""); 38 | } 39 | parsingResult.append(">"); 40 | } else if (event.isCharacters()) { 41 | parsingResult.append(event.asCharacters().getData()); 42 | } else if (event.isEndElement()) { 43 | parsingResult.append(""); 46 | } 47 | } 48 | System.out.println(parsingResult); 49 | } 50 | 51 | public static void writeXMLByStAX() throws XMLStreamException, FileNotFoundException { 52 | XMLOutputFactory factory = XMLOutputFactory.newInstance(); 53 | XMLStreamWriter writer = factory.createXMLStreamWriter(new FileOutputStream("output.xml")); 54 | writer.writeStartDocument(); 55 | writer.writeCharacters(" "); 56 | writer.writeComment("testing comment"); 57 | writer.writeCharacters(" "); 58 | writer.writeStartElement("catalogs"); 59 | writer.writeNamespace("myNS", "http://blog.csdn.net/Chinajash"); 60 | writer.writeAttribute("owner", "sina"); 61 | writer.writeCharacters(" "); 62 | writer.writeStartElement("http://blog.csdn.net/Chinajash", "catalog"); 63 | writer.writeAttribute("id", "007"); 64 | writer.writeCharacters("Apparel"); 65 | // 写入catalog元素的结束标签 66 | writer.writeEndElement(); 67 | // 写入catalogs元素的结束标签 68 | writer.writeEndElement(); 69 | // 结束 XML 文档 70 | writer.writeEndDocument(); 71 | writer.close(); 72 | System.out.println("ok"); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk6/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | /** 5 | * @author zhongqiu 6 | * jdk6的特性 7 | * 参考资料:http://freesea.iteye.com/blog/160133 8 | * 具体特性: 9 | * (1)Compiler API。动态编译Java源文件 10 | * (2)轻量级HttpServer。Http Server API 11 | * (3)对脚本语言的支持如: ruby, groovy, javascript 12 | * (4)【插入式注解处理API】和Common Annotations 13 | * (5)简化Web Services。 14 | * JAX-WS(Java Architecture for XML-Web Services) 2.0。xml-web service 15 | * JAXB(Java Architecture for XML Binding) 2.0。实现对象与XML之间的映射 16 | * Streaming API for XML (STaX)。是继DOM(Document Object Model)和SAX(Simple API for XML)之后的又一种处理xml的api 17 | * 它提供了一个双向API,这个API可以通过一个事件流来读取或者写入XML,其中包括跳过某个部分,然后直接关注与文档中的另外一个小部分的能力。 18 | * (6)Database,绑定Derby。开源嵌入式数据库 Derby(JavaDB) 绑定在JDK 1.6中 19 | * (7)更丰富的Desktop APIs。Desktop类和SystemTray类 。比如启动界面的支持,系统托盘的支持,JTable排序等等。 20 | * (8)用Console开发控制台程序 21 | */ 22 | package zhongqiu.common.jdk6; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/BinaryDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7; 2 | 3 | //支持二进制文字 4 | public class BinaryDemo { 5 | public static void main(String[] args) { 6 | int binary = 0b1001_1001; 7 | System.out.println(binary); 8 | 9 | byte aByte = (byte) 0b001; 10 | System.out.println(aByte); 11 | 12 | short aShort = (short) 0b010; 13 | System.out.println(aShort); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/ColletionsDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | //语法上支持集合,而不一定是数组 11 | public class ColletionsDemo { 12 | public static void main(String[] args) { 13 | 14 | List list = new ArrayList<>(); 15 | list.add("item"); 16 | list.add("item1"); 17 | list.add("item2"); 18 | System.out.println(list.get(0)); 19 | 20 | Set set = new HashSet<>(); 21 | set.add("item"); 22 | set.add("item1"); 23 | set.add("item2"); 24 | System.out.println(set); 25 | 26 | Map map = new HashMap<>(); 27 | map.put("key", 1); 28 | map.put("key1", 2); 29 | map.put("key2", 3); 30 | System.out.println(map.get("key")); 31 | 32 | // List piDigits = [ 1,2,3,4,5,8 ]; 33 | // List list1 = ["1"]; 34 | // 35 | // Set set1 = {"item"}; 36 | // 37 | // Map map1 = {"key" : 1}; 38 | // int value = map1["key"]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/GetEnvironmentDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7; 2 | 3 | 4 | //新增一些取环境信息的工具方法 5 | public class GetEnvironmentDemo { 6 | public static void main(String[] args) { 7 | // System getJavaIoTempDir(); // IO临时文件夹 8 | // 9 | // System.getJavaHomeDir(); // JRE的安装目录 10 | // 11 | // File= System.getUserHomeDir(); // 当前用户目录 12 | // 13 | // File System.getUserDir(); // 启动java进程时所在的目录5 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/TryCatchDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileReader; 5 | import java.io.IOException; 6 | import java.sql.Connection; 7 | import java.sql.SQLException; 8 | import java.sql.Statement; 9 | 10 | //在try catch异常扑捉中,一个catch可以写多个异常类型,用"|"隔开 11 | public class TryCatchDemo { 12 | public static void main(String[] args) { 13 | 14 | // jdk7之前 15 | try { 16 | BufferedReader reader = new BufferedReader(new FileReader("")); 17 | Connection con = null; 18 | Statement stmt = con.createStatement(); 19 | } catch (IOException e) { 20 | e.printStackTrace(); 21 | } catch (SQLException e) { 22 | e.printStackTrace(); 23 | } 24 | 25 | // jdk7 26 | try { 27 | BufferedReader reader = new BufferedReader(new FileReader("")); 28 | Connection con = null; 29 | Statement stmt = con.createStatement(); 30 | } catch (IOException | SQLException e) { 31 | // 捕获多个异常,e就是final类型的 e.printStackTrace(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/TypeInferenceDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | //类型自动推断 <> 9 | public class TypeInferenceDemo { 10 | 11 | List tempList = new ArrayList<>(); 12 | 13 | // 没有使用类型推断 14 | Map> map1 = new HashMap>(); 15 | // 通过类型推断后变成: 16 | Map> map2 = new HashMap<>();// 这个<>被叫做diamond(钻石)运算符,这个运算符从引用的声明中推断类型。 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/ValueWithUnderline.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7; 2 | 3 | //数值可加下划线 4 | //很长的数字可读性不好,在Java 7中可以使用下划线分隔长int以及long了 5 | public class ValueWithUnderline { 6 | public static void main(String[] args) { 7 | int one_million = 1_000_000; 8 | System.out.println(one_million); 9 | int i=1_1 * 10; 10 | System.out.println(i); 11 | int j=120 - 1_________________0; 12 | System.out.println(j); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/VarableParameter.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7; 2 | 3 | import java.util.List; 4 | 5 | //可变参数非具体化是提示警告 6 | public class VarableParameter { 7 | public static void main(String[] args) { 8 | 9 | } 10 | 11 | public static void addToList (List listArg, T... elements) { 12 | for (T x : elements) { 13 | listArg.add(x); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/concurrent/ForkJoinTaskDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7.concurrent; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | import java.util.concurrent.ForkJoinPool; 5 | import java.util.concurrent.ForkJoinTask; 6 | import java.util.concurrent.Future; 7 | import java.util.concurrent.FutureTask; 8 | import java.util.concurrent.RecursiveTask; 9 | 10 | //RecursiveAction:用于没有返回结果的任务。 11 | //RecursiveTask :用于有返回结果的任务。 12 | //双端队列,工作窃取,重写compute方法 13 | //用于可很好分解成子任务的场景 14 | public class ForkJoinTaskDemo { 15 | public static void main(String[] args) throws InterruptedException { 16 | long startTime = System.currentTimeMillis(); 17 | int count = 0; 18 | for (int i = 1; i < 10; i++) { 19 | count = count + i; 20 | Thread.sleep(1000); 21 | } 22 | System.out.println(count); 23 | long endTime = System.currentTimeMillis(); // 获取结束时间 24 | System.out.println("程序运行时间: " + (startTime - endTime) + "ms"); 25 | 26 | long startTime1 = System.currentTimeMillis(); 27 | CountTask countTask = new CountTask(1, 10); 28 | ForkJoinPool forkJoinPool = new ForkJoinPool(); 29 | Future futureTask = forkJoinPool.submit(countTask); 30 | try { 31 | System.out.println(futureTask.get()); 32 | } catch (ExecutionException e) { 33 | // TODO Auto-generated catch block 34 | e.printStackTrace(); 35 | } 36 | long endTime1 = System.currentTimeMillis(); // 获取结束时间 37 | System.out.println("程序运行时间: " + (startTime1 - endTime1) + "ms"); 38 | 39 | } 40 | } 41 | 42 | // RecursiveTask用法,统计1+2+3+.... 43 | class CountTask extends RecursiveTask { 44 | private static final int THRESHOLD = 2; 45 | private Integer start; 46 | private Integer end; 47 | 48 | public CountTask(Integer start, Integer end) { 49 | this.setStart(start); 50 | this.setEnd(end); 51 | } 52 | 53 | @Override 54 | protected Integer compute() { 55 | int count = 0; 56 | if (start - end <= THRESHOLD) { 57 | for (int i = start; i < end; i++) { 58 | count += i; 59 | try { 60 | Thread.sleep(1000); 61 | } catch (InterruptedException e) { 62 | // TODO Auto-generated catch block 63 | e.printStackTrace(); 64 | } 65 | } 66 | } else { 67 | int middle = (end + start) / 2; 68 | CountTask leftTask = new CountTask(start, middle); 69 | CountTask rightTask = new CountTask(middle + 1, end); 70 | leftTask.fork(); 71 | rightTask.fork(); 72 | count = leftTask.join() + rightTask.join(); 73 | } 74 | return count; 75 | } 76 | 77 | public Integer getStart() { 78 | return start; 79 | } 80 | 81 | public void setStart(Integer start) { 82 | this.start = start; 83 | } 84 | 85 | public Integer getEnd() { 86 | return end; 87 | } 88 | 89 | public void setEnd(Integer end) { 90 | this.end = end; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/concurrent/TransferQueueDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk7.concurrent; 2 | 3 | import java.util.concurrent.LinkedTransferQueue; 4 | import java.util.concurrent.TimeUnit; 5 | import java.util.concurrent.TransferQueue; 6 | 7 | //Java7中加入了JSR 166y规范对集合类和并发类库的改进。其中的一项是增加了接口TransferQueue和其实现类LinkedTransferQueue。 8 | //TransferQueue继承了BlockingQueue(BlockingQueue又继承了Queue)并扩展了一些新方法。 9 | //TransferQueue则更进一步,生产者会一直阻塞直到所添加到队列的元素被某一个消费者所消费(不仅仅是添加到队列里就完事)。 10 | //新添加的transfer方法用来实现这种约束。顾名思义,阻塞就是发生在元素从一个线程transfer到另一个线程的过程中, 11 | //它有效地实现了元素在线程之间的传递(以建立Java内存模型中的happens-before关系的方式)。 12 | //LinkedTransferQueue实际上是ConcurrentLinkedQueue、SynchronousQueue(公平模式)和LinkedBlockingQueue的超集。 13 | public class TransferQueueDemo { 14 | private static TransferQueue queue = new LinkedTransferQueue(); 15 | 16 | public static void main(String[] args) throws Exception { 17 | // queue.transfer用法 18 | new Productor1(1).start(); 19 | Thread.sleep(100); 20 | System.out.println("over.size=" + queue.size()); 21 | 22 | // queue.tryTransfer(result, 1, TimeUnit.SECONDS); 用法 23 | new Productor2(1).start(); 24 | Thread.sleep(100); 25 | System.out.println("over.size=" + queue.size());// 2 26 | Thread.sleep(1500); 27 | System.out.println("over.size=" + queue.size());// 1 28 | } 29 | 30 | // transfer(E e) 31 | // 若当前存在一个正在等待获取的消费者线程,即立刻将e移交之;否则将元素e插入到队列尾部,并且当前线程进入阻塞状态,直到有消费者线程取走该元素。 32 | static class Productor1 extends Thread { 33 | private int id; 34 | 35 | public Productor1(int id) { 36 | this.id = id; 37 | } 38 | 39 | @Override 40 | public void run() { 41 | try { 42 | String result = "id=" + this.id; 43 | System.out.println("begin to produce." + result); 44 | queue.transfer(result); 45 | System.out.println("success to produce." + result); 46 | } catch (InterruptedException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | } 51 | 52 | // tryTransfer(E e, long timeout, TimeUnit unit) 53 | // 若当前存在一个正在等待获取的消费者线程,会立即传输给它; 54 | // 否则将元素e插入到队列尾部,并且等待被消费者线程获取消费掉。若在指定的时间内元素e无法被消费者线程获取,则返回false,同时该元素从队列中移除。 55 | static class Productor2 extends Thread { 56 | private int id; 57 | 58 | public Productor2(int id) { 59 | this.id = id; 60 | } 61 | 62 | @Override 63 | public void run() { 64 | try { 65 | String result = "id=" + this.id; 66 | System.out.println("begin to produce." + result); 67 | queue.tryTransfer(result, 1, TimeUnit.SECONDS); 68 | System.out.println("success to produce." + result); 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/concurrent/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | /** 5 | * @author wangzhongqiu 6 | * 7 | */ 8 | package zhongqiu.common.jdk7.concurrent; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk7/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | /** 5 | * @author zhongqiu 6 | * 参考资料:http://www.cnblogs.com/nayitian/p/3406749.html 7 | * jdk1.7特性 8 | * (1)switch中可以使用字串了 9 | * (2)类型自动推断 10 | * (3)数值可加下划线 11 | * (4)支持二进制文字 12 | * (5)【传输队列】transferqueue(tryTransfer,transfer,tryTransfer(E e, long timeout, TimeUnit unit)) 13 | * (6)ForkJoinTask 14 | * (5)在try catch异常扑捉中,一个catch可以写多个异常类型,用"|"隔开 15 | * (6)自动资源管理。 16 | * jdk7之前,你必须用try{}finally{}在try内使用资源,在finally中关闭资源,不管try中的代码是否正常退出或者异常退出。 17 | * jdk7之后,你可以不必要写finally语句来关闭资源,只要你在try()的括号内部定义要使用的资源。 18 | * (7)可变参数非具体化时提示警告 19 | * (8)新增一些取环境信息的工具方法 20 | */ 21 | package zhongqiu.common.jdk7; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/DateAPIDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk8; 2 | 3 | //Date API 4 | public class DateAPIDemo { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/FI.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk8; 2 | 3 | //函数式接口:我们把这些只拥有一个方法的接口称为 函数式接口。也叫作 单抽象方法类型 4 | // 因为 默认方法 不算抽象方法,所以你也可以给你的函数式接口添加默认方法。 5 | // Lambda表达式会被编译器转换成相应函数式接口的一个实例 6 | // FI fI = (from) -> Integer.valueOf(from); 7 | // Integer converted = fI.convert("123"); 8 | // System.out.println(converted); 9 | @FunctionalInterface 10 | public interface FI { 11 | T convert(F from); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/InterfaceDefaultMethod.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk8; 2 | 3 | //接口的默认方法 4 | public class InterfaceDefaultMethod { 5 | interface Formula { 6 | double calculate(int a); 7 | 8 | default double sqrt(int a) { 9 | return Math.sqrt(a); 10 | } 11 | } 12 | 13 | public static class FormulaImpl implements Formula { 14 | 15 | @Override 16 | public double calculate(int a) { 17 | // TODO Auto-generated method stub 18 | return 0; 19 | } 20 | 21 | } 22 | 23 | public static void main(String[] args) { 24 | FormulaImpl formulaImpl = new FormulaImpl(); 25 | System.out.println(formulaImpl.sqrt(36)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/Lambda.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leon66666/JavaCommon/4af0fc8f1de2c86e4bfdd0d7d12f1b6308e9b9b0/src/main/java/zhongqiu/common/jdk8/Lambda.java -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/OptionalDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk8; 2 | 3 | import java.util.Optional; 4 | 5 | //Optional 6 | //http://www.runoob.com/java/java8-optional-class.html 7 | 8 | //Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。 9 | //Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。 10 | //Optional 类的引入很好的解决空指针异常。 11 | public class OptionalDemo { 12 | public static void main(String[] args) { 13 | Integer value1 = null; 14 | Integer value2 = new Integer(10); 15 | 16 | // Optional.ofNullable - 允许传递为 null 参数 17 | Optional a = Optional.ofNullable(value1); 18 | 19 | // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException 20 | Optional b = Optional.of(value2); 21 | System.out.println(sum(a, b)); 22 | } 23 | 24 | public static Integer sum(Optional a, Optional b) { 25 | 26 | // Optional.isPresent - 判断值是否存在 27 | System.out.println("第一个参数值存在: " + a.isPresent()); 28 | System.out.println("第二个参数值存在: " + b.isPresent()); 29 | 30 | // Optional.orElse - 如果值存在,返回它,否则返回默认值 31 | Integer value1 = a.orElse(new Integer(0)); 32 | 33 | // Optional.get - 获取值,值需要存在 34 | Integer value2 = b.get(); 35 | return value1 + value2; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/StringJoinDemo.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk8; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | public class StringJoinDemo { 7 | public static List fruitList = Arrays.asList("Apple", "Banan", "Orange", "Pear"); 8 | 9 | public static void main(String[] args) { 10 | System.out.println(String.join(", ", fruitList)); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/TargetType.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.jdk8; 2 | 3 | //目标类型 4 | //对于给定的 lambda 表达式,它的类型是由其上下文推导而来 5 | //类型自动推导 6 | public class TargetType { 7 | 8 | // 由于目标类型(函数式接口)已经“知道” lambda 表达式的形式参数(Formal 9 | // parameter)类型,所以我们没有必要把已知类型再重复一遍。也就是说,lambda 表达式的参数类型可以从目标类型中得出: 10 | // Comparator c = (s1, s2) -> s1.compareToIgnoreCase(s2); 11 | // 在上面的例子里,编译器可以推导出 s1 和 s2 的类型是 String。此外,当 lambda 12 | // 的参数只有一个而且它的类型可以被推导得知时,该参数列表外面的括号可以被省略: 13 | // 14 | // FileFilter java = f -> f.getName().endsWith(".java"); 15 | // button.addActionListener(e -> ui.dazzle(e.getModifiers())); 16 | // 这些改进进一步展示了我们的设计目标:“不要把高度问题转化成宽度问题。”我们希望语法元素能够尽可能的少,以便代码的读者能够直达 lambda 17 | // 表达式的核心部分。 18 | // 19 | // lambda 表达式并不是第一个拥有上下文相关类型的 Java 表达式:泛型方法调用和“菱形”构造器调用也通过目标类型来进行类型推导: 20 | // List ls = Collections.emptyList(); 21 | // List li =Collections.emptyList(); Map m1 = new 22 | // HashMap<>(); 23 | // Map m2 = new HashMap<>(); 24 | 25 | } -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/jdk8/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author zhongqiu 3 | * 参考资料: http://blog.csdn.net/lingzhm/article/details/44946873 4 | * 【深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)】 5 | * http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 6 | * 【Java 8 中的 Streams API 详解】 7 | * http://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html 8 | * jdk1.8特性 9 | * (1)接口的默认方法 10 | * (2)Lambda 表达式:stream操作,中间操作,最终操作;stream转换成其他数据格式;串行和并行stream;动态生成lambda表达式的高阶函数; 11 | * (3)函数式接口:我们把这些只拥有一个方法的接口称为 函数式接口。也叫作 单抽象方法类型【FI】 12 | * (4)目标类型【TargetType】,类型自动推导 13 | * (5)方法引用 14 | * (6)Stream API 15 | * (7)Date API 16 | * (8)Optional 类 17 | */ 18 | package zhongqiu.common.jdk8; -------------------------------------------------------------------------------- /src/main/java/zhongqiu/common/utils/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.utils; 2 | 3 | /** 4 | * Created by wangzhongqiu on 2017/8/16. 5 | */ 6 | public class CommonUtils { 7 | public static void swap(int[] array,int i,int j){ 8 | int temp = array[i]; 9 | array[i] = array[j]; 10 | array[j] = temp; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/SortCompare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leon66666/JavaCommon/4af0fc8f1de2c86e4bfdd0d7d12f1b6308e9b9b0/src/main/resources/SortCompare.png -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/CodeBlock03.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | 3 | /** 4 | * @author wangzhongqiu 5 | * @date 2018/1/4. 6 | */ 7 | public class CodeBlock03 { 8 | public static void main(String[] args) { 9 | Object o=new Object(); 10 | final int i = 3; 11 | Code code = new Code(); 12 | code.setI(1); 13 | String str = "sss"; 14 | switch (i) 15 | 16 | { 17 | 18 | case '1': 19 | 20 | System.out.println(1); 21 | 22 | break; 23 | 24 | case 2: 25 | 26 | System.out.println(2); 27 | 28 | break; 29 | 30 | default: 31 | 32 | System.out.println("default"); 33 | 34 | break; 35 | 36 | } 37 | } 38 | } 39 | 40 | class Code { 41 | public int i; 42 | 43 | public int getI() { 44 | return i; 45 | } 46 | 47 | public void setI(int i) { 48 | this.i = i; 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/Main.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | /** 3 | * 赛码网例题 4 | */ 5 | 6 | 7 | import java.util.Date; 8 | import java.util.Scanner; 9 | 10 | public class Main { 11 | private static final ThreadLocal threadLocal = new ThreadLocal(); 12 | private static final ThreadLocal threadLocal1 = new ThreadLocal(); 13 | 14 | public static void main(String[] args) { 15 | Integer integer = 111; 16 | threadLocal.set(integer); 17 | threadLocal1.set(integer); 18 | Thread thread = Thread.currentThread(); 19 | Date now=new Date("20170102"); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/test.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | 3 | import java.util.concurrent.ArrayBlockingQueue; 4 | 5 | public class test { 6 | public static void main(String[] args) { 7 | ArrayBlockingQueue arrayBlockingQueue=new ArrayBlockingQueue(4); 8 | try { 9 | arrayBlockingQueue.put(1); 10 | } catch (InterruptedException e) { 11 | e.printStackTrace(); 12 | } 13 | try { 14 | arrayBlockingQueue.take(); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/test1.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import java.util.Scanner; 10 | import java.util.concurrent.atomic.AtomicInteger; 11 | 12 | /* 13 | * 天猫国际每天都会卖出很多跨境商品,用户每次下单可能购买多个商品,购买总数小于10件,由于海关规定,每一个进入海关的箱子里面的商品总额不能超过2000元(否则不能清关)所以当用户下单总金额超过2000,必须使用多个箱子分开包装运输;现在为了节约运输成本,希望在满足海关的要求下,能够使用尽可能少的箱子。 14 | 注: 15 | 每个商品都有自己的单价,有特定的长宽高,所有商品都是长方体 16 | 商品可以横放、竖放、侧放,但不用考虑斜放,但是长宽高各项总和必须都要小于等于箱子的长宽高 17 | 假定目前天猫国际使用同一种规格的箱子 18 | boxLong,boxWidth,boxHigh 19 | (箱子长,箱子宽,箱子高) 20 | 21 | 某用户下单买了如下商品 22 | n(商品件数) 23 | item1Price,item1Long,item1With,item1High 24 | item2Price,item2Long,item2With,item2High 25 | item3Price,item3Long,item3With,item3High 26 | item4Price,item4Long,item4With,item4High 27 | ... 28 | (商品价格,商品长,商品宽,商品高) 29 | (所有输入类型均为int型正整数) 30 | 31 | 请你算出需要使用最小的箱子数量,可以将这些商品顺利得清关送到消费者手中,如果无解,输出-1 32 | * */ 33 | public class test1 { 34 | private static int CUSTOMS_LIMIT_MONEY_PER_BOX = 2000; 35 | private static Model[] items; 36 | private static int boxMinNum = 0; 37 | 38 | private static int process() { 39 | return -1; 40 | } 41 | 42 | public static void main(String args[]) { 43 | Scanner scanner = new Scanner(System.in); 44 | boxTemplate.price = CUSTOMS_LIMIT_MONEY_PER_BOX; 45 | 46 | while (scanner.hasNext()) { 47 | boxTemplate.length = scanner.nextInt(); 48 | boxTemplate.width = scanner.nextInt(); 49 | boxTemplate.height = scanner.nextInt(); 50 | 51 | int itemNum = scanner.nextInt(); 52 | items = new Model[itemNum]; 53 | for (int i = 0; i < itemNum; i++) { 54 | Model item = new Model(); 55 | item.price = scanner.nextInt(); 56 | item.length = scanner.nextInt(); 57 | item.width = scanner.nextInt(); 58 | item.height = scanner.nextInt(); 59 | items[i] = item; 60 | } 61 | long startTime = System.currentTimeMillis(); 62 | boxMinNum = Integer.MAX_VALUE; 63 | System.out.println(process()); 64 | } 65 | } 66 | 67 | public static class Model { 68 | public int price; 69 | public int length; 70 | public int width; 71 | public int height; 72 | } 73 | 74 | public static class boxTemplate { 75 | public static int length; 76 | public static int width; 77 | public static int height; 78 | public static int price; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/test2.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | 3 | 4 | import java.util.Scanner; 5 | 6 | public class test2 { 7 | public static void main(String[] args) { 8 | Scanner sc = new Scanner(System.in); 9 | int n = sc.nextInt(); 10 | int[] a = new int[n]; 11 | for (int i = 0; i < n; i++) { 12 | 13 | } 14 | for (int i = 0; i < n; i++) { 15 | a[i] = sc.nextInt(); 16 | } 17 | int first = a[0]; 18 | int index = 0; 19 | for (int i = 1; i < a.length; i++) { 20 | if (a[i] > first) { 21 | first = a[i]; 22 | index = i; 23 | } 24 | } 25 | for (int i = 0; i < a.length; i++) { 26 | if (i == index) 27 | continue; 28 | first -= a[i]; 29 | } 30 | 31 | if (first > 0) 32 | System.out.println("no"); 33 | else 34 | System.out.println("yes"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/test3.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | import java.util.Scanner; 3 | /** 4 | * Created by hxb002 on 2017/8/31. 5 | */ 6 | public class test3 { 7 | public static void main(String[] args) { 8 | Scanner scan = new Scanner(System.in); 9 | int num = scan.nextInt(); 10 | int[] arr = new int[num]; 11 | for (int i = 0; i < num; i++) { 12 | arr[i] = scan.nextInt(); 13 | } 14 | int goalNum = scan.nextInt(); 15 | long sum = 0; 16 | int index = 0; 17 | for (int i = num; i > 0; i--) { 18 | for (int j = 0; j <= num - i; j++) { 19 | while (index != num) { 20 | sum = sum + arr[j]; 21 | index++; 22 | } 23 | index = 0; 24 | if (sum % goalNum == 0) { 25 | System.out.println(i); 26 | return; 27 | } 28 | } 29 | } 30 | System.out.println(0); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/test4.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | 3 | import javafx.beans.binding.ObjectExpression; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/9/8. 7 | */ 8 | public class test4 { 9 | static int cnt = 0; 10 | 11 | public static void main(String[] args) { 12 | Other o = new Other(); 13 | new test4().addOne(o); 14 | System.out.println(o.i); 15 | } 16 | 17 | public void addOne(final Other o) { 18 | o.i++; 19 | } 20 | } 21 | 22 | class Other { 23 | public int i; 24 | } -------------------------------------------------------------------------------- /src/test/java/zhongqiu/common/test/test5.java: -------------------------------------------------------------------------------- 1 | package zhongqiu.common.test; 2 | 3 | import java.util.concurrent.locks.ReentrantReadWriteLock; 4 | 5 | /** 6 | * Created by wangzhongqiu on 2017/9/8. 7 | */ 8 | public class test5 extends ReentrantReadWriteLock{ 9 | public static void main(String[] args) { 10 | Double a = Double.valueOf(5); 11 | Double b = Double.valueOf(6); 12 | System.out.println(a.compareTo(b)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Book 4 | Video 5 | -------------------------------------------------------------------------------- /usefilelocks.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leon66666/JavaCommon/4af0fc8f1de2c86e4bfdd0d7d12f1b6308e9b9b0/usefilelocks.txt -------------------------------------------------------------------------------- /writesomebytes.txt: -------------------------------------------------------------------------------- 1 | aome bytes.z --------------------------------------------------------------------------------