Archive

Archive for October, 2009

Maybe Another Choice for QQ?

October 28th, 2009 西坪 No comments

QQ is the only choice to communicate with friends for most Chinese. And now, it’s a cash cow for Tencent Inc. They control everything, ask your money all the time. Some money for service is reasonable, but they even demand your money when you want more privacy. For an example, when you want to remove which blog you have visited, you must become their paid user.

How to build another simple, strong, easy to control by user himself/herself, no money-accquired function and cheap system to give another choice? As my imagine,

1st, Openness. Everyone can build new function for himself and who likes the function. Users build the system by themselves.
2nd, Users make decision. Everything is controlled by the users community. Even if whether the project should continue or stop.
3rd, No business goal. The main system may supported by users’ denotation.
4th, Distributed and reliable. Maybe it would like tor, eMule? Most computation is executed on the volunteers’ machine. The center server may serve a index.
5th, Secured and spam-free.

To build that system, the road map may like below:

1st, a few architects build the start-up system and open it to more developers.
2nd, many volunteers compose of a support community, and it broadcast by itself.

It must be the source that everything is controlled by users, made by users.

Categories: $IT Thoughts Tags:

动态规划练习(一): 求数列中连续数字之和的最大值

October 23rd, 2009 西坪 No comments

问题:

给你n个数a[1], a[2], …, a[n],(0[1]。

这个题目看上去与动态规划很类似,在于其解的特点。设数列的前 n 个数的最大值为 F(n),则:

dp_num_seqs_larger

证明从略。

代码如下:

package com.feihoo.test;
 
public class MaxSequenceValue {
 
	static int[] nums = { 2, 4, -3, 9, 30, -30, 20, 0, 34, -2, -45, 12, -8, 11 };
 
	public static void main(String[] args) {
		int minLen = 2;
		int maxLen = 4;
 
		int[] m = new int[nums.length];
		m[minLen - 1] = 0;
 
		for (int i = minLen; i < nums.length; i++)
			compute(i, m, minLen, maxLen);
 
		int largest = m[minLen];
		for (int i = minLen + 1; i < nums.length; i++)
			if (largest < m[i])
				largest = m[i];
 
		System.out.println(largest);
	}
 
	private static void compute(int n, int[] m, int minLen, int maxLen) {
		m[n] = m[n - 1];
		for (int len = minLen; len < maxLen && n - len >= 0; len++) {
			int re = nums[n];
			for (int i = n - 1; i > n - len; i--)
				re += nums[i];
			if (m[n] < re)
				m[n] = re;
		}
	}
}

参考:

1. 来源: 动态规划习题

理解Java虚拟机的加法运算

October 16th, 2009 西坪 No comments

在CSDN博客诗剑书生的专栏,作者提到了short类型的+操作和++操作的区别,竟然没有一个正确答案。其实这个问题没那么复杂,关键是要了解Java计算的最小单位和理解类型的自动转型。
原问题是:

short tmp = 0;
为什么tmp = tmp +1;错误但 tmp ++;却正确.

理解这个问题,先要理解实现计算的基本原理。Java虚拟机是一种进程虚拟机,它负责解释和执行字节码,跟直接运行在硬件上运行汇编指令是有区别的。普通的机器语言可以直接操作寄存器完成计算,寄存器能够表示的最小单位是字节。而Java的计算是基于栈的,并规定其基本操作单位是一个字。字的实际大小是有虚拟机的设计者来决定的,虚拟机规范只是规定一个字长要能够放下一个 byte、short、 int、 char、float等类型。所以byte、short、char的运算都像 int 一样是在以字为单位来计算的,尽管它本身比字还要小。

此时我们不难理解,tmp+1会得到一个int。根据Java的类型语义,可以向上转型,不会自动向下转型。所以 tmp = tmp+1语法错误, 关键在 = 符号这里。那为什么 tmp++就是正确的呢? 因为++ 只有一个操作数,不涉及转型的问题, 不像 = 符号。简单比对下二者生成的字节码。

	short a = 2;
	a++;

生成的字节码如下,其中的第5行指令执行了自动转型,i2s指定是int类型的数据转换为short类型的数据。

  0:   iconst_2
  1:   istore_1
  2:   iload_1
  3:   iconst_1
  4:   iadd
  5:   i2s
  6:   istore_1
  7:   return

我们在看看 int c = a+b 生成的字节码:

	short a = 2;
	short b = 111;
	int c = a + b;

生成字节码如下:

   0:   iconst_2
   1:   istore_1
   2:   bipush  111 #压栈111
   4:   istore_2
   5:   iload_1  #加载a到栈
   6:   iload_2  #加载b到栈
   7:   iadd  
   8:   istore_3  #将计算结果存到局部变量c中
   9:   return

该文中提到的另一个错误:

short c = a + b

其实是一个原理,尽管a,b,c 都是short, 但是 a+b 实际上得到了是int, 于是不能自动转型为 short 给 c。

Categories: $Programming Tags: ,

细节背后:为什么线程协作之前必须先获得锁?

October 3rd, 2009 西坪 No comments

为什么Object.wait()/notify()/notifyAll() 之前必须获得锁? 这是JLS的规定。Wait-notify机制是围绕监控器锁进行的,获得锁是很自然的前提,自身没有拿到锁之前,怎么能够尝试去操作靠锁来调控的线程呢?不过今天偶尔有时间,就看下Sun Hotspot是怎么实现这一机制的。

当我们执行下面的代码时,线程会抛出异常java.lang.IllegalMonitorStateException: current thread not owner。

public class WaitNotifyCompilerCode {
	private String aString = "Hello World!";
 
	public static void main(String[] args) {
		System.out.println("Execute start ....");
		final WaitNotifyCompilerCode w = new WaitNotifyCompilerCode();
		w.wait1SecAndPrintString();
		System.out.println("Execute end ....");
	}
 
	public void wait1SecAndPrintString() {
		try {
			this.wait(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(aString);
	}
 
}

异常栈的信息如下:

Exception in thread "main" java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.wait(Native Method)
	at com.feihoo.test.waitnotify.WaitNotifyCompilerCode.wait1SecAndPrintString(WaitNotifyCompilerCode.java:35)
	at com.feihoo.test.waitnotify.WaitNotifyCompilerCode.main(WaitNotifyCompilerCode.java:27)

深入查看 OpenJDK的源码,找到 Object.wait() 函数本地代码:

JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
  JVMWrapper("JVM_MonitorWait");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  assert(obj->is_instance() || obj->is_array(), "JVM_MonitorWait must apply to an object");
  JavaThreadInObjectWaitState jtiows(thread, ms != 0);
  if (JvmtiExport::should_post_monitor_wait()) {
    JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
  }
  ObjectSynchronizer::wait(obj, ms, CHECK);
JVM_END

重点看倒数第二行,调用的函数如下面的代码:

// NOTE: must use heavy weight monitor to handle wait()
void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
  if (UseBiasedLocking) {
    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
  }
  if (millis < 0) {
    TEVENT (wait - throw IAX) ;
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
  }
  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
  DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
  monitor->wait(millis, true, THREAD);

而上面的代码中最后一行的函数里,在做实际操作之前调用了下面的宏:

// A macro is used below because there may already be a pending
// exception which should not abort the execution of the routines
// which use this (which is why we don't put this into check_slow and
// call it with a CHECK argument).
 
#define CHECK_OWNER()                                                             \
  do {                                                                            \
    if (THREAD != _owner) {                                                       \
      if (THREAD->is_lock_owned((address) _owner)) {                              \
        _owner = THREAD ;  /* Convert from basiclock addr to Thread addr */       \
        _recursions = 0;                                                          \
        OwnerIsThread = 1 ;                                                       \
      } else {                                                                    \
        TEVENT (Throw IMSX) ;                                                     \
        THROW(vmSymbols::java_lang_IllegalMonitorStateException());               \
      }                                                                           \
    }                                                                             \
  } while (false)
Categories: $Programming Tags: , ,