Java中的SoftReference,WeakReference和PhantomReference

SoftReference,WeakReference和PhantomReference都是继承自Reference抽象类,

在这个类中有一个static代码块,会给当前线程组和它的所有父亲都启动一个线程叫做ReferenceHandler,

ReferenceHandler会随时来检查是否有pending中是否有GC加入的已经清除的对象,然后将它们加入到Reference对于的ReferenceQueue中。

/* High-priority thread to enqueue pending References
 */
private static class ReferenceHandler extends Thread {

    ReferenceHandler(ThreadGroup g, String name) {
        super(g, name);
    }

    public void run() {
        for (;;) {

            Reference r;
            synchronized (lock) {
                if (pending != null) {
                    r = pending;
                    Reference rn = r.next;
                    pending = (rn == r) ? null : rn;
                    r.next = r;
                } else {
                    try {
                        lock.wait();
                    } catch (InterruptedException x) { }
                    continue;
                }
            }

            // Fast path for cleaners
            if (r instanceof Cleaner) {
                ((Cleaner)r).clean();
                continue;
            }

            ReferenceQueue q = r.queue;
            if (q != ReferenceQueue.NULL) q.enqueue(r);
        }
    }
}

static {
    ThreadGroup tg = Thread.currentThread().getThreadGroup();
    for (ThreadGroup tgn = tg;
         tgn != null;
         tg = tgn, tgn = tg.getParent());
    Thread handler = new ReferenceHandler(tg, "Reference Handler");
    /* If there were a special system-only priority greater than
     * MAX_PRIORITY, it would be used here
     */
    handler.setPriority(Thread.MAX_PRIORITY);
    handler.setDaemon(true);
    handler.start();
}

https://weblogs.java.net/blog/2006/05/04/understanding-weak-references

http://www.cnblogs.com/blogoflee/archive/2012/03/22/2411124.html

Java中的finally

1. 在try中return后,finally是否会执行?

2. 在try中throw exception后,finally是否会执行?

3. 在try中System.exit(0)后,finally是否会执行?

例子:

public class Test2 {
    public static void main(String[] args) throws Exception {
        returnValue();
        tryException();
        exit();
    }

    public static int returnValue() {
        try{
            return 0;
        } finally {
            System.out.println("finally in returnValue");
        }
    }

    public static void tryException() throws Exception {
        try{
            throw new Exception("My exception");
        } finally {
            System.out.println("finally in tryException");
        }
    }

    public static void exit() {
        try{
            System.exit(0);
        } finally {
            System.out.println("finally in exit");
        }
    }

}

以下是屏幕输出:

finally in returnValue
finally in tryException
Exception in thread “main” java.lang.Exception: My exception
at other.Test2.tryException(Test2.java:21)
at other.Test2.main(Test2.java:7)

Java中的内部类

Java的内部类分为四种:

static inner class:可以访问static变量和方法

inner class:可以访问static变量和方法;可以访问类变量和类方法

local class:可以访问final变量,static变量和方法;如何在非static方法中,可以访问类变量和类方法

anonymous class:可以访问final变量,static变量和方法;如何在非static方法中,可以访问类变量和类方法

下面时它们的使用方法:

OuterClass.java

public class OuterClass {
    static class StaticNestedClass {
        public void printIt() {
            System.out.println("StaticNestedClass");
        }
    }

    class InnerClass {
        public void printIt() {
            System.out.println("InnerClass");
        }
    }

    public static void main(String[] args) {
        StaticNestedClass c1 = new StaticNestedClass();
        c1.printIt();
    }
}

Test.java

import other.OuterClass.InnerClass;
import other.OuterClass.StaticNestedClass;

public class Test {
    public static void main(String[] args) {
        StaticNestedClass c1 = new StaticNestedClass();
        c1.printIt();

        OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
        nestedObject.printIt();

        //inner class
        OuterClass oc = new OuterClass();
        InnerClass c2= oc.new InnerClass();
        c2.printIt();

        class LocalClass {
            public void printIt() {
                System.out.println("LocalClass");
            }
        }

        LocalClass lc = new LocalClass();
        lc.printIt();

        LocalClass lc2 = new LocalClass() {
            @Override
            public void printIt() {
                System.out.println("AnonymousClass");
            }
        };
        lc2.printIt();

        PrintInterface pi = new PrintInterface() {

            @Override
            public void printIt() {
                System.out.println("AnonymousClass2");    
            }

        };
        pi.printIt();
    }

    interface PrintInterface {
        public void printIt();
    }

}

以下时屏幕输出:

StaticNestedClass
StaticNestedClass
InnerClass
LocalClass
AnonymousClass
AnonymousClass2

Java 8中的Lambda

Lambda是什么,就是没有名字的函数。

Lambda的语法

  • A comma-separated list of formal parameters enclosed in parentheses.

  • The arrow token, ->

  • A body, which consists of a single expression or a statement block.

下面是有两个参数的Lambda的例子。

public class Calculator {

    interface IntegerMath {
        int operation(int a, int b);   
    }

    public int operateBinary(int a, int b, IntegerMath op) {
        return op.operation(a, b);
    }

    public static void main(String... args) {

        Calculator myApp = new Calculator();
        IntegerMath multi = (a, b) -> a * b;
        IntegerMath divide = (a, b) -> a / b;
        System.out.println("40 * 2 = " +
            myApp.operateBinary(40, 2, multi ));
        System.out.println("20 / 10 = " +
            myApp.operateBinary(20, 10, divide));    
    }
}

http://jdk8.java.net/download.html
下载jdk8,然后安装。我下载的是Linux 64位的,只需要解压就可以使用。

在使用之前需要设置环境变量export PATH=~/download/jdk1.8.0/bin/:$PATH,然后编译和运行;

[jdk1.8.0]$ javac Calculator.java
[jdk1.8.0]$ java Calculator
40 * 2 = 80
20 / 10 = 2

如果我们把

myApp.operateBinary(40, 2, multi )

改成

myApp.operateBinary(40, 2, (a, b) -> a *b)

也时可以的。但是JDK时如何知道我们的Lambda就是IntegerMath呢?

答案时JDK不知道,它只是将Lambda转成IntegerMath然后使用的。这就是Target Typing。

To determine the type of a lambda expression, the Java compiler uses the
target type of the context or situation in which the lambda expression was
found. It follows that you can only use lambda expressions in situations in
which the Java compiler can determine a target type:

  • Variable declarations

  • Assignments

  • Return statements

  • Array initializers

  • Method or constructor arguments

  • Lambda expression bodies

  • Conditional expressions, ?:

  • Cast expressions

http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

Android系统的改进(六)-- 没有所有启动程序一览

尽管Android号称多任务系统,但是如果我启动多个程序时,程序之间相互切换很是麻烦。

我要记住锁启动的时那些程序,然后按Home键返回,再点击我要切换的程序。

为什么不再下拉列表中显示所有启动的程序,便于切换呢?

发现不是所有的程序启动后,会将自己加入到下拉列表中,只有一部分会,比如“墨迹天气”

Android系统的改进(五)-- 没有精确的电量提醒功能

用户不知道当前的电池剩余量,只能在自己感觉快没有电的时候,去充电。

如果有这个功能的话,我就会在电池剩余量只有~5%时去充电。

或者在打电话时,不知道电池剩余量,手机会自动关机,影响用户使用。

如果有这个功能的话,我就会在电池剩余量只有~5%时去充电,而不会影响通话

现在只能通过第三方软件来实现,为什么不加入到系统中呢?

Android系统的改进(四)-- 短信直接加入黑名单功能

经常我们会收到很多的垃圾短信,希望可以将收到信息的号码加入黑名单。

但是C8813提供的安全卫士,只能先打开,然后选择“从短信列表中添加”,

这样的用户体验很差。

所有我们可以在短信列表中提供一个选项“加入黑名单”,可以立即加入,而不是要打开安全卫士,再做一系列操作。

scons是如何处理 -C和 --site-dir

/usr/bin/scons –debug=pdb -j4 -C /your/project/dir –site-
dir=/yours/scons/site_scons

1. -j4 表示同时可以并行4个job

2. -C scons在做任何事情之前,先转到-
C指定的目录,这会使得scons首先会在/your/project/dir目录下面找SConstruct文件去执行

3. –site-dir
会使得scons在执行自己的SConstruct文件之前,先执行/yours/scons/site_scons目录下的site_init.py

SCons/Script/Main.py 使得你自己的site被加载到上下文中,并且将site追加到PYTHONPATH中:

def _load_site_scons_dir(topdir, site_dir_name=None):
    """Load the site_scons dir under topdir.
    Adds site_scons to sys.path, imports site_scons/site_init.py,
    and adds site_scons/site_tools to default toolpath."""
    if site_dir_name:
        err_if_not_found = True       # user specified: err if missing
    else:
        site_dir_name = "site_scons"
        err_if_not_found = False

    site_dir = os.path.join(topdir.path, site_dir_name)
    if not os.path.exists(site_dir):
        if err_if_not_found:
            raise SCons.Errors.UserError("site dir %s not found."%site_dir)
        return

    site_init_filename = "site_init.py"
    site_init_modname = "site_init"
    site_tools_dirname = "site_tools"
    sys.path = [os.path.abspath(site_dir)] + sys.path
    site_init_file = os.path.join(site_dir, site_init_filename)
    site_tools_dir = os.path.join(site_dir, site_tools_dirname)
    if os.path.exists(site_init_file):
        **import imp**
        # TODO(2.4): turn this into try:-except:-finally:
        try:
            try:
                fp, pathname, description = imp.find_module(site_init_modname,
                                                            [site_dir])
                # Load the file into SCons.Script namespace.  This is
                # opaque and clever; m is the module object for the
                # SCons.Script module, and the exec ... in call executes a
                # file (or string containing code) in the context of the
                # module's dictionary, so anything that code defines ends
                # up adding to that module.  This is really short, but all
                # the error checking makes it longer.
                try:
                    m = sys.modules['SCons.Script']
                except Exception, e:
                    fmt = 'cannot import site_init.py: missing SCons.Script module %s'
                    raise SCons.Errors.InternalError(fmt % repr(e))
                try:
                    # This is the magic.
                    **exec fp in m.__dict__**
                except KeyboardInterrupt:
                    raise
                except Exception, e:
                    fmt = '*** Error loading site_init file %s:\n'
                    sys.stderr.write(fmt % repr(site_init_file))
                    raise
            except KeyboardInterrupt:
                raise
            except ImportError, e:
                fmt = '*** cannot import site init file %s:\n'
                sys.stderr.write(fmt % repr(site_init_file))
                raise
        finally:
            if fp:
                fp.close()
    if os.path.exists(site_tools_dir):
        SCons.Tool.DefaultToolpath.append(os.path.abspath(site_tools_dir))

SCons/Script/SConsript.py使得SConstruct文件在当前上下文中被执行:

# Append the SConscript directory to the beginning
# of sys.path so Python modules in the SConscript
# directory can be easily imported.
sys.path = [ f.dir.get_abspath() ] + sys.path

# This is the magic line that actually reads up
# and executes the stuff in the SConscript file.
# The locals for this frame contain the special
# bottom-of-the-stack marker so that any
# exceptions that occur when processing this
# SConscript can base the printed frames at this
# level and not show SCons internals as well.
call_stack[-1].globals.update({stack_bottom:1})
old_file = call_stack[-1].globals.get('__file__')
try:
    del call_stack[-1].globals['__file__']
except KeyError:
    pass
try:
    try:
        **exec _file_ in call_stack[-1].globals**
    except SConscriptReturn:
        pass
finally:
    if old_file is not None:
        call_stack[-1].globals.update({__file__:old_file})

如何debug scons

什么时scons,参见: http://scons.org/

你可以使用命令行:

/usr/bin/scons –debug=pdb youparas

或者在Eclipse中debug,如下:

1. 首先找到scons的安装路径,然后将它添加到PYTHONPATH中,

$ rpm -ql scons
/usr/bin/scons
/usr/bin/scons-2.0.43
/usr/bin/scons-time
/usr/bin/scons-time-2.0.43
/usr/bin/sconsign
/usr/bin/sconsign-2.0.43
/usr/lib/scons/SCons/Action.py

如下图:

2. 新建一个python工程,然后将scons复制到新建的工程里面,就可以debug了