存档

‘程序人生’ 分类的存档

深入浅出Future Pattern

2013年6月24日 没有评论

前几天看hdfs QJM的代码,里面看到一个ListenableFuture,说实话对于Java,目前我还只是通过看代码,遇到没见过的再去查的方式,也着实是没有时间和精力再去通篇研读诸如《thinking in Java》这样的大砖块了,现在这样的方式,目前来说应该是够用了。重点还是放在系统和业务上,语言本身本不应该成为障碍。言归正传,回到ListenableFuture, 在网上看了一下相关的资料,把它的来龙去脉了解了一下,在这里记录一下。

前面提到的ListenableFuture, 是google开源的自己的Java Library Guava(http://code.google.com/p/guava-libraries/)中的一个模块,它本身是继承是Java的Future。严格来讲,Future是一种Design Pattern, 它本身跟语言是没有关系的。最新的C++11中,也加入了Future的支持,不过笔者以前写C++的时候,C++11还没正式发布,加上它本身也是比较新的,主流的编译器支持的本身也不是很好,因此只是知道它的存在,并没有去研究过它是做什么的,怎么来使用的。接下来,我会通过一些Java的Future的例子,来一步步介绍Future及其用法。

简单来讲,Future是这样一种Pattern: 它本身表示‘将来(future)’,你提交一个异步的任务,比如提交到一个threadpool,与此同时拿到一个Future对象,任务的执行是异步的,这时候你可以去做其它的事情,等到异步任务结束的时候,你可通过前面的Future对象拿到异步执行的任务的结果。下面通过一个简单的例子来直观感受一下Future: 阅读全文…

Log4j学习笔记

2013年3月17日 2 条评论

用了三四年的C++,转向Java的怀抱,还是有诸多的不适应。C++中不论多复杂的Server,只要有GDB在手,总感觉debug都不是啥大事,程序运行期间的各种状态,都可以通过GDB轻松的获取到;而到了Java中,总感觉像是被困住了手脚,有力没法使,不知道是我还掌握方法,还是事实确实如此,发现Server端的Java程序,几乎没有什么好的debug的方法。也跟一些用了几年Java的朋友聊过,大多给出的答案都是Log。以前在学校刚开始学C/C++的时候,那时候的debug就是靠printf,基本思想跟Log是一样的, 后来结识了神器GDB之后,就深深地爱上了它。现在用上了Java之后,感觉又一夜回到了解放前。我并不是说Log不重要,相反,在越复杂的系统中,Log的地位越发重要,但是对于debug而言,一点点的加Log, 然后重新编译,布署,效率实在是太低了。对于像Java这样没有GDB这样的神器的语言,Log的地位越发重要,因此像Log4j这样的组件就非常流行,前段时间在弄hadoop中异步log相关的一些事情,就顺便把log4j学习了一下,下面整理了一下log4j相关的一些内容。

1. Log4j online manual
地址:http://logging.apache.org/log4j/1.2/manual.html
本文的大部分内容是参考了这个manual,外加一些其他人的博客。
阅读全文…

Haskell学习笔记(1)

2012年7月21日 4 条评论

之前看过一些对函数式编程(Function Programming,简称FP)的介绍,一直想通过学习一门FP的语言,来深入了解一下FP。Haskell,就是众多FP语言中的一门,它是一门纯粹的FP语言,是学习FP不错的选择。今天这篇文章主要是对Haskell的一个简单介绍,以及一些正式开始学习之前的准备工作。

  • 1. 什么是Haskell
  • Haskell, 是一门纯粹的函数式的程序设计语言,它是基于Lambda Calculus的。做为一门函数式的语言(Funcitonal Language),与传统的命令式的语言(Imperative Language)相比,它的主要优势在于,代码更为简洁,可靠性更好,语义非常直观,在很大程度上提高了程序员的产出率。
    在开始学习Haskell之前,我们先来看一个例子,相信通过这个例子,读者朋友会对Haskell有一个直观的印象,想学习FP的朋友,会爱上Haskell的:

    1
    2
    
    qsort [] = []
    qsort (p:xs) = qsort [x | x< -xs, x<p] ++ [p] ++ qsort [x | x<-xs, x>=p]

    上面是一个Haskell版本的quick sort,学习过C/C++/Java等命令式语言的朋友,应该知道通过命令式语言实现的quicksort, 大概需要10-20行的代码。相比而言,Haskell版本的quick sort,是多么的简洁、直观。下面简单解释一下上面的代码:第一行是初始化,输入一个空的list, 返回也是一个空的list; 第二行,qsort的输入一个list,把这个list分成两部分,一部分是单独的元素p, 一部分是除去p之外剩下的部分xs,xs也是一个list. 那么,对入p:xs这个list排序的结果就是:对xs中小于p的部分排序的结果,p和对xs中不小于p的部分排序的结果这三部分组成的list。Isn’t it amazing? 阅读全文…

分类: Haskell 标签:

C++模板类继承中的Name Lookup

2012年6月26日 5 条评论

今天这篇文章说说C++中的模板类继承时的名称(变量/类型)查找(Name Lookup)。普通的继承关系中的Name Lookup对于熟悉C++的同学来说,都是非常直观的,因此在这里就不再赘言。模板类(Template Class)的继承中,由于模板本身特殊性,使其在Name Lookup时,有着一定的特殊性,我们从一个例子来说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template< typename T>
class A
{
protected:
    int m_data;
};
 
template< typename T>
class B : public A< T>
{
public:
    void Test(int t)
    {   
        m_data = t;
    }   
};
 
int main(int argc, char** argv)
{
    B< int> b;
    b.Test();
}

阅读全文…

jQuery and Highcharts

2012年4月3日 没有评论

最近新做的系统刚刚上线,前段时间的努力终于有了阶段性的成果,可以小小的庆贺一下。当然,这只是题外话了,主要目的是为了引入今天的正题——Jquery和Highcharts。在进入正式的内容之前,有必要先简单介绍一下jQuery和Highcharts分别是什么:
jQuery (http://jquery.com)
jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.
(jQuery是一个快速、简洁的Javascript库,它的主要功能是简化Html文档的遍历、事件处理、动画和ajax交互,从而加快web端的开发。jQuery设计的初衷是改变程序员使用Javascript写程序的方式。)

Highcharts (http://www.highcharts.com)
Highcharts is a charting library written in pure JavaScript, offering intuitive, interactive charts to your web site or web application. Highcharts currently supports line, spline, area, areaspline, column, bar, pie and scatter chart types.
(Highchars是一个用纯Javascript写的图表绘制的库,它可以为你的web app提供直观、交互式的图表。当前,用Highcharts可以实现直线图、曲线图、区域图、曲线区域图、柱状图、条形图、饼图、散点图等一系列的图表。) 阅读全文…

谈谈定时器(Timer)的使用

2012年3月11日 1 条评论

过去的半年,陆陆续续看过不少新同学写的代码,自己也写了不少代码。在这过程中,还是有不少感触的。我们知道,定时器(Timer)在程序中的是非常有用的一种utility。今天这篇文章,就结合自己看代码、写代码过程中的一些经验,来谈谈定时器的使用,包括基本的用法,还有使用过程中的一些误区。

在介绍定时器的使用之前,先简单介绍一下常见的定时器的实现。通常,定时器的是由一个单独的线程+一个最小堆来实现的。单独的线程基本上保证定时事件不被其他事件而阻塞,能够及时调度到,从而保证定时器的在时间上的“准确性”;用最小堆来做为核心的数据结构,主要是为了性能考虑,以时间为key,这样堆顶的元素就是最先到期的,因此每次check的时候,直接从堆顶开始check, 只到遇到第一个没到期的元素为止,这里的复杂度与在堆里的元素个数无关,可以看作是O(1)的,因此性能上还是比较有保障的。

接下来说说定时器的基本用法,通常情况下,定时器有两类主要的应用:一类是周期性的执行某个指定的动作;一类是延后特定的时间,执行指定的动作。第一类我们通常叫周期性定时器(PeriodTimer),第二类叫一次型定时器(OneshotTimer) 。 阅读全文…

分类: 程序人生 标签: ,

Christmas – HTML5

2011年12月25日 5 条评论

今天是Christmas, 首先向所有的亲人和朋友们道一声Merry Christmas,天气冷了,大家注意防寒。 早上,看到Cnbeta的头条是一个关于程序员的故事—-程序猿的HTML5圣诞礼物,讲的是一个程序员朋友用HTML5给自己女朋友做的一个Christmas礼物,想必所有的程序员朋友的GF看了都会有点暖暖的感觉。一直以来,听大家讲HTML5,自己也没去了解过,一个人的Christmas,正好了解一下HTML5。

1. 什么是HTML5?
HTML5是指新版本的HTML,最近的一个版本是4.01,于1999年发布,自此之后就没做过什么大的改动,HTML5是下一代的HTML。现在,HTML5的标准还没有正式发布,但是主流的浏览器(包括IE, Chrome, Firefox, Safari)等已陆续开始支持HTML5的特性了。 阅读全文…

分类: 程序人生 标签: ,

谈谈程序的封装

2011年12月11日 4 条评论

近半年来,团队加入了不少新同学,陆陆续续也看过不少新同学写的代码,一个比较大的感受是,新同学程序的逻辑上问题不会太大,但是代码的封装方面,还是有明显的不足。具体主要包括以下几个方面,一是命名,包括类、函数、变量等的,一个好的名字,可以让读程序的人一看到它就大概知道它是做什么用的;二是函数、类的划分,哪些实体应该抽象为一个类,这个实体的那些功能该抽象成函数,这是程序设计中最为重要的内容;三是线程安全,在多线程环境下,线程安全是一个很重要的话题,很多时候因为封装的不合理,导致使用上的不方便,更为严重的是造成死锁等的问题。下面就分别从这三个方面,谈一些自己的看法,希望能够对初入职场的新同学有所帮助。

第一个方面是命名,这个是最为基本的内容。可以这样讲,把写程序比做写文章,命名对于程序的作用,就相当于措词对于文章,好的措词对于一篇好的文章的作用,不用我再多说。关于程序中的命名,主要包括三种,一是类型名,二是函数名,三是变量名。类型名在C++中应对的包括class, struct, enum等,它们都是抽象出来的一个实体,因此它们的名字最好是一个名词,或者名词词组,比如PCManager,它是一个PC管理器类型。 阅读全文…

漫话C++0x(六)—- variadic templates

2011年11月20日 3 条评论

熟悉printf/scanf的朋友应该对C/C++中的变参函数不陌生,它可以支持任意个数的参数。模板(template)在C++中的地位相信不用我再多说,但是,一直以来,C++模板不支持变参,这成了模板一个被诟病的地方,在很多使用场景限制了模板的威力。举例来说,同样语义的模板函数,因为参数个数不定,有若干个,这样的场景之下,我们只能通过枚举的方式来实现。这样的方法,一方面使得代码本身不够简洁,另一方面因为枚举只能做到有限个数的参数,还是在一定程度上限制了使用的灵活性。现在,C++0x引入了变参模板,上面讲的问题便迎刃而解了,这对C++程序员朋友们来说是莫大的福音。下面我们先看一个简单的例子,先对变参模板有一个直观的印象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include < iostream>
#include < string>
 
void Print()
{
    std::cout < < "\n";
}
 
template< typename T, typename ... TRest>
void Print(const T& obj, const TRest& ... rest)
{
    std::cout < < obj << " ";
    Print(rest ...);
}
 
int main()
{
    double p = 3.14;
    std::string s("pi");
    Print(p, &p, s, &s);
}

阅读全文…

漫话C++0x(五)—- thread, mutex, condition_variable

2011年11月6日 6 条评论

熟悉C++98的朋友,应该都知道,在C++98中没有thread, mutex, condition_variable这些与concurrency相关的特性支持,如果需要写多线程相关程序,都要借助于不同平台上各自提供的api,这样带来的问题就是程序的跨平台移植性比较差,经常要用一大堆的#ifdef WIN32类似的宏来区分不同的平台,搞得程序很难看。C++0x最原始的初衷之一就是为了让C++的功能更加强大,更加方便使用。现如今硬件如此发达,concurrency在程序设计中已经是司空见惯的事情了,如果C++再不支持这些concurrency相关的特性,就真的out了。现在,C++程序员的福音到了,C++0x提供了对thread, mutex, condition_variable这些concurrency相关特性的支持,以后多线程这一块的代码可以完全跨平台了,而且由于C++0x封装的都比较好,代码写起来也十分简洁。下面开始介绍今天的内容。

  • 1. thread
  • 写过多线程程序的朋友,相信对thread本身都不会陌生,这里不对thread本身做太多的说明,以介绍C++0x中提供的thread的用法为主。请大家先看下面的例子: 阅读全文…

推荐一个课程

2011年10月30日 12 条评论

一直以来,对机器学习这个领域比较感兴趣,但由于平时所做的工作与这个方面关系不大,所以一直也没有深入、系统的学习过。但由于比较感兴趣,所以平时也零零散散地了解过一些相关的内容。小时候读书的时候,听老师说21世纪是信息爆炸的时代,现在是真真切切的感受到了。随着人们可用的信息量越来越大,如何在如此庞大的信息海洋中找到对自己有用的信息,成为了一个越来越重要的领域。而机器学习,在这个领域中的作用越来越大,越发觉得它将是未来改变世界的一把利剑。举几个生活中比较常见的例子,现在比较火的一些sns社区中的个性化推荐引擎,这个东西威力真的很大,它通过对已有数据的‘学习’,然后把你感兴趣的事物推荐给你,从人们主动去搜索,到被动的被推荐,这中间有一个质的飞越,毕竟人的本性都是懒惰的,再说很多时候,并不是每个人都清楚的知道自己喜欢什么,而推荐引擎所推荐的,很多时候都是你喜欢的,这个够神奇吧。再举一个垃圾邮件的例子,相信几年前email刚流行起来的时候,大家对这个事情都比较头疼。垃圾邮件的处理,也是一个很好的机器学习的例子,基本的思路是通过对已有的一些垃圾邮件进行特征提取,然后利用这些特征和垃圾邮件数据训练出一个识别垃圾邮件的模型,做的好的这样的模型准确率和召回率都还是挺不错的,现在像qq和163这些邮箱的邮件反垃圾还都不错的。这些机器学习相关的例子,都是与我们的生活关系非常密切的,信息技术越发达,机器学习的作用越大,我称之为可以改变世界的一把利剑。 阅读全文…

漫话C++0x(四) —- function, bind和lambda

2011年10月23日 4 条评论

本文是C++0x系列的第四篇,主要是内容是C++0x中新增的lambda表达式, function对象和bind机制。之所以把这三块放在一起讲,是因为这三块之间有着非常密切的关系,通过对比学习,加深对这部分内容的理解。在开始之间,首先要讲一个概念,closure(闭包),这个概念是理解lambda的基础。下面我们来看看wikipedia上对于计算机领域的closure的定义:

A closure (also lexical closure, function closure or function value) is a function together with
a referencing environment for the non-local variables of that function.

上面的大义是说,closure是一个函数和它所引用的非本地变量的上下文环境的集合。从定义我们可以得知,closure可以访问在它定义范围之外的变量,也即上面提到的non-local vriables,这就大大增加了它的功力。关于closure的最重要的应用就是回调函数,这也是为什么这里把function, bind和lambda放在一起讲的主要原因,它们三者在使用回调函数的过程中各显神通。下面就为大家一步步接开这三者的神秘面纱。

  • 1. function
  • 我们知道,在C++中,可调用实体主要包括函数,函数指针,函数引用,可以隐式转换为函数指定的对象,或者实现了opetator()的对象(即C++98中的functor)。C++0x中,新增加了一个std::function对象,std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的)。我们来看几个关于function对象的例子: 阅读全文…

    分类: 程序人生 标签: , , , , ,

    再谈“事件驱动”

    2011年10月16日 1 条评论

    之前也写过一些关于事件驱动模型的文章,事隔一年多,再谈起事件驱动,又是一种新的感触,借此文来分享一下,希望能够帮助到在工作、学习中在这方面遇到困惑的朋友。

    通常,我们会把轮询和事件驱动拿来做对比,关于它们两者,我在《浅淡“事件驱动”》一文中有举过一个传统邮件和电子邮件的例子,可以帮助大家来理解。轮询的最大缺点是盲目的做,CPU浪费很严重;事件驱动解决了浪费CPU的问题,它只在需要做的时候做,但是在实现上相对要复杂一些。不过总的来说,再复杂的模型,只要理解了它的原理,都阻挡不了聪明的人类使用它的步伐。

    工作的两三年的时间里,陆陆续续也做过不少项目,写过不少程序。每次写新的程序,或者是看别人写的程序,都多多少少对会反思自己以前写的程序中使用过的一些模型,想着如何来改进它,使得程序的可扩展性,可复用性等越来越好。通过这样的一些过程,自己也确实发现了变化,也积累了一些经验,总结一下,分享给大家。接下来我将通过一些实例,来介绍事件驱动模型在实现的过程中需要注意的一些点。 阅读全文…

    手把手教你玩转GDB(2)—在GDB中玩转STL(ppt)

    2011年10月1日 19 条评论

    上周给team成员分享的—-GDB系列第二弹—-主要内容是分析STL中常用容器的结构,教大家如何在GDB中玩转STL,让STL的调试不再头疼。如果对GDB不是很熟的朋友,我之前推出过一系列的GDB相关的文章,可以先看一下之前的文章,然后再看这个会轻松一些。之前的GDB系列文章参见下面的“相关文章”列表。下面是flash版的PPT,大家可以先堵为快:

    Get Adobe Flash player


    如果觉得flasht版不够给力的朋友,可以在下面留言,向我索取原始的ppt版本,记得留下邮箱地址。或者到新浪微博,收听小武哥博客(http://weibo.com/zeshengwu),然后给我发私信索取,谢谢!

    漫话C++0x(三)

    2011年9月24日 没有评论

    本文是《漫话C++0x》系列的第三篇,接前面的内容,继续为大家介绍一些C++0x中增加的比较好玩的特性。我们知道变量的初始化在C++中是一个比较重要的话题,好的编程习惯建议大家在声明变量的时候最好初始化,这样可以避免一些不必要的问题。另外,在C++98中,变量的初始化(initialization)和赋值(assignment)是两个比较重要的概念,这里大家可以回顾一下,比如常量只能初始化,不能赋值。

    今天要讲的主要内容就是C++0x中新增加的统一初始化的语法,通过与C++98中的对比,我们来加深对C++0x的理解。下面我们来看一些C++98中初始化的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    /// 各种形式的初始化
    const int x(5);           ///< 直接初始化
    const int y = 5;          ///< copy构造初始化
    int arr[] = {1, 2, 3};    ///< 大括号初始化
    struct Point{int x, y;};
    const Point p = {1, 2};   ///< 大括号初始化
    class PointX
    {
    public:
        PointX(int x, int y);
    private:
        int x, y;
    };
    const PointX px(1, 2);    ///< 构造函数初始化
    std::vector< int> vec(arr, arr+3); ///< 从别的容器初始化

    阅读全文…