Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

Java5新特性

27
Apr
2007

Java5新特性

By Alex
/ in Java
/ tags 并发编程, 新特性
0 Comments
泛型(Generics)
简介

泛型,也称为参数化类型,是很多语言支持的编程范式——在定义类型、接口或者方法时将类型作为参数。Java诞生以来最重大的语法改变当属泛型,它是Java5最重要的特性。Java泛型与C++的模板机制在形式上有些类似,但是Java泛型的实现方式——类型擦除导致二者有着根本性的不同。

使用泛型,可以获得以下好处:

  1. 在编译期获得更好的类型检查
  2. 消除不必要的强制转型代码
  3. 允许编程人员实现泛型算法

使用泛型机制设计的类,最常见的是容器类,Java5的集合框架大量使用了泛型机制(类似于C++的STL库):

Java
1
2
3
4
5
public interface Collection<E>{};
public interface Set<E>{};
public interface List<E>{};
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{};
public interface Map<K,V> {}

但是,任何字段、方法参数、方法返回值需要参数化的类型,都可以从泛型机制获益,例如下面这个通用的回调接口: 

Java
1
2
3
interface Callback<P,R>{
    R invoke(P p);
}
类/接口的泛型化

所谓泛型类型( generic type),是指通过类型参数化的类/接口,这种类型的声明语法为:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
class ClassName<T1,...Tn>{
    // T1...Tn是将ClassName参数化的类型形参(type parameter),或者叫类型变量(type variables),可以有1-N个
}
// 示例:
class Container<I> {
    private I item;
    void put(I i) {
        item = i;
    }
    I get() {
        return item;
    }
}

类型形参可以在类定义的任何地方引用。类型参数只是一个占位符,它可以表示任意一种非基本(non-primitive )类型。根据惯例,类型形参使用单个大写字母表示,一般E表示“元素”、K表示“键”、N表示“数字”、T表示“类型”、V表示“值”,等等。

要在代码中使用一个泛型类型,必须进行泛型类型调用(generic type invocation),此时必须把类型形参(type parameter)替换为类型实参( type argument),后者是真实的Java类型:

Java
1
2
3
Container<Number> cn = new Container<Number>();
// Java 7引入了钻石操作符,可以根据cn的变量类型推倒构造器的type argument:
Container<Number> cn = new Container<>();

作为类型实参的Java类型,其本身也可以是泛型类型:

Java
1
2
3
4
// 不管嵌套多少层,泛型类型的类型参数都不能是占位符
Container<List<String>> cn = new Container<>();
// 下面的语句非法,E不是可解析的真实类型
Container<List<E>> cn = new Container<>();
原始类型(Raw Types)

所谓原始类型,是指在不指定类型实参的情况下使用泛型,例如: ArrayList list = new ArrayList() 。原始类型为依赖的Java库提供的向后兼容。

混合使用泛型、原始类型,会在编译时得到未检查错误信息(Unchecked Error Messages),所谓Unchecked表示编译器无法得到足够的信息来完成类型推断以确保安全性。要禁止此类错误信息,可以使用编译选项 -Xlint:-unchecked 或者在代码上添加注解 @SuppressWarnings("unchecked") 

方法的泛型化

不但类可以设计为泛型,方法也可以。方法可以使用类声明的泛型形参,亦可自己声明泛型参数,声明自己的泛型参数的方法称为泛型方法(Generic method),例如:

Java
1
2
3
4
5
6
public class Math {
    // 泛型方法,泛型形参列表必须在返回值之前声明:
    public static <RET, ARG0, ARG1> RET plus( ARG0 arg0, ARG1 arg1 ) {
        return (RET) null;
    }
}

调用泛型方法的完整语法如下:

Java
1
Integer result = Math.<Integer, Double, Double>plus( 1.1, 1.2 );

指定泛型实参列表 不是必须的,通常编译器能够根据上下文推断。编译器的这种能力称为type inference。

受限(Bounded)泛型形参

Java泛型支持限制可作为泛型实参的类型的范围。例如上面的plus方法,可能仅仅支持数字类型。要声明受限泛型形参,需要使用extends关键字:

Java
1
2
3
public static <RET, ARG0 extends Number, ARG1 extends Number> RET plus( ARG0 arg0, ARG1 arg1 ) {
    return (RET) null;
}

使用受限形参,方法体可以对形参的类型进行假设,这样就可以执行有意义的方法调用了:

Java
1
2
3
4
5
6
7
8
public static <T extends Comparable<T>> int countGreaterThan( T[] anArray, T elem ) {
    int count = 0;
    for ( T e : anArray )
        // 调用比较方法,因为T必须是Comparable的子类型
        if ( e.compareTo( elem ) > 0 )
            ++count;
    return count;
} 
多重限制(Multiple Bounds) 

可以在限制泛型实参必须是某个类型或者其子类型的同时,限制它必须实现某些接口:

Java
1
2
// 多个接口用 & 符号分隔
public static <T extends Entity & Serializable> void save(T t){}
泛型通配符(Wildcard)

可以在字段、方法形参、变量的声明中使用(不受限的)泛型通配符,使用 ? 代替实际类型即为泛型通配符,表示泛型实参的类型未知。使用通配符后:

  1. 泛型类中返回参数类型的方法,类型自动变为Object
  2. 泛型类中需要参数类型作为入参的方法,将不能接受任何对象

例如泛型类:

Java
1
2
3
4
5
6
7
8
9
10
11
12
public class Value<T> {
    private T t;
    public Value( T t ){
        this.t = t;
    }
    public void set( T t ){
        this.t = t;
    }
    public T get(){
        return t;
    }
}

如果声明参数类型为通配符:

Java
1
2
3
Value<?> value = new Value<Integer>( 1 );
Object o = value.get(); //可以通过编译,你不知道是什么类型,所以我们给你一个根类型
value.set( 1 ); //无法通过编译,不是我们不限制类型,而是你不知道是什么类型

就意味着,你可以从泛型对获取参数类型对象,但是却不能提供了。 

受限泛型通配符

Java 5还支持受限泛型通配符的声明,所谓受限是指,变量/返回值/参数的泛型参数必须满足限制:

  1. Type<? extends PType> :上限通配符(Upper Bounded Wildcard),表示变量的类型参数必须是PType或者PType的子类型
  2. Type<? super PType> :下限通配符(Lower Bounded Wildcard),表示变量的类型参数必须是PType或者PType的超类型

在设计一个接收泛型入参的接口时,如果你需要向入参提供一个对象,可以使用下限通配符,因为这可以确保你提供的对象可以被接受:

Java
1
2
3
4
5
6
public static void addNumbers( List<? super Integer> list ) {
    // list的实参可以是Integer,或者Number,或者Object,但是必然能容纳int类型
    for ( int i = 1; i <= 10; i++ ) {
        list.add( i );
    }
}

在设计一个接收泛型入参的接口时,如果你需要使用入参提供的对象,可以使用上限通配符,这样你可以假设对象的类型:

Java
1
2
3
4
5
6
public static void process( List<? extends Number> list ) {
    // list的实参可以是Integer,或者Number,或者Double,但是都可以针对其调用Number的接口
    for ( Number n : list ) {
        n.intValue();
    }
}

上面的两条,就是所谓的PECS原则:当泛型对象作为生产者(对外提供对象)时,将其泛型形参声明为上限通配符(extends);当泛型对象作为消费者时,将其泛型形参声明为下限通配符(super) ,下面的例子有助于进一步理解PECS:

Java
1
2
3
4
5
6
7
8
9
10
11
Value<? extends Number> valueExtend = new Value<Integer>( 1 );
//有了这个变量声明,我知道类型参数必然是Number的子类型:
Number num = valueExtend.get();
//但是,具体是Integer,还是Double,我不知道,因此我无法提供参数类型的实例
valueExtend.set( 1 ); //无法编译
 
Value<? super Number> valueSuper = new Value<Number>( 1 );
//有了这个变量声明,我知道类型参数必然是Number的超类型:
valueSuper.set( new Integer( 1 ) ); //那么,我当然可以提供Number的子类型给你
//但是,我却不知道类型参数的真实类型
Object obj = valueSuper.get(); //所以此变量提供的参数类型未知
数组与泛型
Java
1
2
3
4
class BoundedBuffer<T>
{
    private T[]             items;
}

但是,就像不能实例化参数类型一样,你也不能实例化参数类型的数组:

Java
1
2
T t = new T();        //无法通过编译,无法提供数组需要的运行时信息
T[] ts  = new T[10];  //无法通过编译,编译器甚至无法确认T类型有默认构造器

不能实例化的原因是,Java中的数组在运行时必须知道其元素的类型。上述语法无法提供这一类型信息——因为T是什么在编译时根本不知道。因此泛型数组如果需要在泛型内部初始化,必须进行变通:

Java
1
T[] ts = (T[]) new Object[10];
类型擦除(Type Erasure)

注意绝大部分的参数化类型信息都在编译期间擦除了,除了继承自泛型类的子类型,可以通过反射得到父类上的真实参数类型:

Java
1
2
3
4
5
6
7
8
9
//它的泛型父类的类型信息String不会被擦除
class StringList extends ArrayList<String> //和C++的模板特化有些类似
{
    private static final long serialVersionUID = 1L;
}
 
//可以使用下面的代码获得泛型父类的真实参数类型
ParameterizedType type = (ParameterizedType) new StringList().getClass().getGenericSuperclass();
assert ( type.getActualTypeArguments()[0] == String.class );
协变

需要注意泛型是“非协变”的,参数类型不同的泛型变量不能相互转换,即使这些参数类型之间存在继承关系:

Java
1
2
3
4
//数组是协变的
Object oa[] = new Integer[] {};
//泛型不是,尽管泛型实参Object和Number具有父子类关系。但是List<Object>、List<Number>之类不存在父子类关系
List<Object> ol = new ArrayList<Number>(); //无法编译

使用上限通配符,可以解决非协变特性导致的无法赋值问题:

Java
1
List<? extends Object> ol = new ArrayList<Number>();  
泛型子类化

继承泛型类型时,可以将全部或者部分泛型参数“特化”:

Java
1
2
3
4
// 完全特化
abstract class StringList implements List<String> {}
// 部分特化
abstract class StringKeyMap<V> implements Map<String,V> {}

注意:上面的例子中,任何StringList是List的子类型,StringKeyMap是Map的子类型。在特化类型参数的同时,你可以获得重写父类逻辑的机会。

其它新特性
注解(Annotation)

注解在Java5中第一次成为可以影响编程方式的语言元素,注解可以为类、字段、方法、甚至注解本身提供元数据信息。注解的出现将很大程度上改变可配置化对XML高度依赖的现状。

声明注解需要使用特殊的类型说明符: @interface ,例如:

Java
1
2
3
4
5
6
7
8
9
10
11
//某些注解可以用来修饰注解类型本身
@Retention ( RetentionPolicy.RUNTIME )
//提示该注解需要在运行期保留
@Target ( ElementType.METHOD )
//提示该注解只能作用于方法上
@interface AutoExtAjaxResult
{
    //注解中可以声明多个“方法”,用来指示注解实例的属性名
    String value(); //value是一个特殊属性,如果注解只有这一个属性,在实例化注解时,可以不指定属性名
    Class<?> type() default App.class; //注解属性可以提供默认值
}

需要注意的是,注解属性只支持有限的类型:基本类型、字符串、注解、枚举、Class,或者这些类型的一维数组。

要使用(实例化)注解,只需要在目标类/方法/字段的声明前面添加@注解名,并提供必要的参数,所有没有提供默认值的属性都需要提供值:

Java
1
2
3
4
5
@AutoExtAjaxResult ( "Avalue" )
public String userInfo()
{
    return null;
}

要在运行时获取某个类/方法/字段上被附加的注解,需要使用反射机制,例如:

Java
1
App.class.getMethod( "userInfo" ).getAnnotation( AutoExtAjaxResult.class ).value(); // Avalue
For/In循环结构

数组以及任何实现了 java.lang.Iterable 接口的对象都可以使用该语法:

Java
1
2
3
4
5
6
for ( char c : new char[] { 'H', 'E', 'L', 'L', 'O' } ) {
    System.out.println( c );
}
for ( String str : new ArrayList() ) {
    System.out.println( str );
}
自动拆装箱

现在基本类型与其包装类型的转换,可以自动进行了:

Java
1
2
3
4
5
6
Number n = 1L;
Double d = 1.1d;
Boolean b = false;
boolean bp = Boolean.TRUE;
double dp = Double.valueOf( 1.1d );
long lp = new Long( 1l );
类型安全的枚举

Java5中,枚举被作为一种特殊的类,可以使用enum关键字来声明,枚举类型不支持创建新实例。

枚举类型和普通类一样可以有字段、方法、构造器等部分,特别的是,枚举实例可以对方法进行覆盖。

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public enum Color
{
    RED( "FF0000" ),
    GREEN( "00FF00" ),
    BLUE( "0000FF" )
    {
        //每个枚举值可以覆盖方法
        public String toString()
        {
            return "00F";
        }
    };
    //和普通类一样,枚举可以具有字段、方法、构造器
    private String code;
 
    private Color( String code )
    {
        this.code = code;
    }
 
    @Override
    public String toString()
    {
        return code;
    }
}
可变长参数

特殊的语法可以声明方法接受不定长度的参数,变长参数的声明必须位于形参列表的尾部:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main( String[] args )
{
    varargsMethod( 1, 2, "1", "2", "3" );
    varargsMethod0( "1", "2", "3" );
}
 
private static void varargsMethod0( String... strs )
{
}
 
private static void varargsMethod( int i, int j, String... strs )
{
}
静态导入

可以使用import static语法导入某些类中的静态方法,在当前文件中不需要提供这些类的名字就可以直接调用静态方法:

Java
1
2
3
4
5
6
import static java.util.Collections.*;
 
public static void main( String[] args )
{
    sort( list ); //不需要提供Collections类名
}
java.util.concurrent包

这是一个Java5引入的专门用于并发编程的新包,该包主要有以下组件:

  1. 支持并发的集合类型,位于java.util.concurrent包
  2. 原子操作类,这些原子操作类受益于JVM引入了CAS(Compare-And-Set)机制,位于java.util.concurrent.atomic包
  3. 新的同步原语,主要是一些锁类,位于java.util.concurrent.locks包
  4. 并发相关工具,例如线程池、信号量等
  5. 异步相关类,例如Future、Executor

concurrent中的集合类图如下(深色表示JDK 1.6追加):

patterns_Concurrent

可以看到类很多,因此不一一描述,仅将类名中单词的含义列在下表:

单词 含义 
Queue 提供先进先出的操作接口
Deque 不但支持在列表的尾部操作,还支持在头部操作
Concurrent 表示支持线程安全的并发访问
Linked 表示链表结构
Array 表示数组结构(连续内存,高速随机访问)
Blocking 当集合为空,取数据操作将阻塞;当集合为满,存数据操作将阻塞
Synchronous 一个存操作的完成,必须依赖有一个取操作的执行
Priority 允许元素被优先取出
Delay 元素只有在超时后,才能从集合中取出
CopyOnWrite 一旦执行写操作,就复制底层的数据结构(例如数组),复制的成本较高,但是CopyOnWrite避免了同步开销,适用于大量读、很少写的应用场景
Navigable 可以导航,即根据给定的元素,寻找其最近的元素

concurrent.atomic包中的原子操作类包括:Boolean、Integer、Long、引用的原子类及其数组类型。

concurrent.locks包引入了一些用于支持锁定的类和接口,改变了Java只能依靠 synchronized 关键字进行粗粒度同步控制的现状:

patterns_Concurrent_Lock

该包主要有三个接口:

 接口/类 说明 
Lock

用于代替 synchronized 关键字的功能,可以关联多个 Condition) ,一般锁都是独占的进行共享资源的访问。该接口提供了比 synchronized 更灵活的功能:

  1. tryLock() 允许尝试性的获得锁,如果失败,立即返回而不是必须陷入等待
  2. lockInterruptibly() 进行锁定,如果其它线程持有锁,那么让当前线程陷入等待。但是这种等待是可中断的。其它线程可以调用该线程的 interrupt() 中断该线程的等待
  3. tryLock(long, TimeUnit) 允许尝试性的获得锁,如果在指定时间内还没有得到锁,则返回
Condition

用于代替 java.lang.Object 定义的监视器方法:wait、notify和notifyAll。该接口可以把前面几个监视器方法的职责分解为多个完全不同的“条件”对象,条件对象总是和一个锁关联。

  1. 当前持有锁的线程,可以等待一个条件的达成: Condition.await() ,从而放弃锁,并陷入等待
  2. 当前持有锁的线程,可以声明一个条件已经达成: Condition.signal() ,从而唤醒一个线程,或者调用 Condition.signalAll() 唤醒所有线程
  3. 被唤醒的线程将立即尝试获得锁,因为它放弃锁时,处于同步区中
ReadWriteLock

维护一对相关的锁:一个用于只读操作,另外一个用于写入操作,规则如下:

  1. 如果当前没有线程持有写锁,那么多个线程可以依次获得读锁
  2. 如果当前没有线程持有锁,那么某个线程可以持有写锁
  3. 如果当前有线程持有写锁,那么其它线程不能获得任何锁
  4. 如果当前有线程持有读锁,那么其它线程可以获取读锁,单不能获取写锁

和异步编程有关的接口主要有四个:

  1. Future接口表示一个“在未来某个时间点可用的结果”
  2. Callable表示一个可调用对象
  3. Executor接口可以用来执行一个Runnable
  4. CompletionService则可用来调用Callable并(异步)获得结果

这些类的层次结构如下:

patterns_Concurrent_Async

concurrent包包含的其它工具类有:

 类 说明 
Semaphore 信号量,线程可以释放信号量,亦可尝试获取信号量,信号量相当于维护了一个固定数量的许可
CountDownLatch 计数器,可以让某个线程在计数完毕前等待。其它线程则可以降低计数值
CyclicBarrier 屏障,允许多个线程相互等待(await),直到所有线程都调用了await(),所有线程才会继续运行
TimeUnit 这是一个枚举,可以用来进行时间单位的转换,或者让当前线程睡眠一段时间
← Oracle数据库知识集锦
Velocity学习笔记 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • Java8新特性
  • Java7新特性
  • Java线程与并发编程
  • Python并发编程
  • Linux信号、进程和会话

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2