随笔 - 8, 文章 - 0, 评论 - 6, 引用 - 0
数据加载中……

2007年7月18日

实现一个栈,使其push,pop,min(取得栈中的最小元素)均为O(1)

实现一个栈,使其push,pop,min(取得栈中的最小元素)均为O(1)

我的解
interface IntStack
{
    
int pop();
    
void push(int i);
    
int get();
}


class MinStack
{
    
//store all the element
    private IntStack elemStack = new IntStack();
    
    
//store current and historical smallest element
    private IntStack minStack = new IntStack();
    
    
public void push(int i)
    
{
        elemStack.push(i);
        
        
int currentMin = minStack.get();
        
if(i <= currentMin) minStack.push(i);
    }

    
    
public int pop()
    
{
        
int result = elemStack.pop();
        
if(result == minStack.get()) minStack.pop();
        
return result;
    }

    
    
public int getMinElem()
    
{
        
return minStack.get();
    }

}

posted @ 2007-07-18 20:57 Job Hu 阅读(894) | 评论 (0)编辑 收藏

二叉排序树变为双向链表

把一个二叉排序树(也许不叫这个)变为递增的双向链表,不能够生成额外的结点.
eg 6
       / \
      4   8
     / \ / \
    3  5 7  9

3=4=5=6=7=8=9

我的解:

class Node
{
    
public Node left;
    
public Node right;
    
    
private static Node getLinkListTail(Node head)
    
{
        Node result 
= head;
        
if(result==nullreturn null;
        
while(result.right!=null)
        
{
            result 
= result.right;
        }

        
return result;
    }

    
    
public static Node flatten(Node root)
    
{
        
if(root==nullreturn null;
        
        Node result 
= root;
        
        
// A leaf node
        if(root.left==null&&root.right==nullreturn root;
        
        
//divide-and-conquer
        Node leftSubTreeLinkListHead = flatten(root.left);
        Node rightSubTreeLinkListHead 
= flatten(root.right);
        
        
//merge
        Node leftSubTreeLinkListTail = getLinkListTail(leftSubTreeLinkListHead);
        root.left 
= leftSubTreeLinkListTail;
        root.right 
= rightSubTreeLinkListHead;
        
if(leftSubTreeLinkListHead!=null
        
{
            result 
= leftSubTreeLinkListHead;
            leftSubTreeLinkListTail.right 
= root;
        }

        
if(rightSubTreeLinkListHead!=null) rightSubTreeLinkListHead.left = root;
        
        
return result;
    }

}


posted @ 2007-07-18 20:37 Job Hu 阅读(641) | 评论 (0)编辑 收藏

2007年7月17日

Byte in Java


public class ByteTest
{
    
public static void main(String[] args)
    
{
        
byte b;
        
byte c;
        
//b = 255; //Cannot convert from int to byte
        
//b = 0xFF; //Cannot convert from int to byte
        b = 127;
        c 
= 0x7F;
        
if(b == c) System.out.println("b == c");
        
if(127 == 0x7F) System.out.println("127 == 0x7F");
        
        b 
= -128;
        
//c = 0x80; //Cannot convert from int to byte
        c = (byte)0x80;
        
if(b == c) System.out.println("b == c");
        
if(-128 == 0x80) System.out.println("-128 == 0x80");
        
if(128 == 0x80) System.out.println("128 == 0x80"); 
        
        c 
= (byte)0x80;
        
if(128 == c) System.out.println("128 == c");
        
if(-128 == c) System.out.println("-128 == c");
        
if(128 == (c&0xFF)) System.out.println("128 == (c&0xFF)");
    }

}

输出:
b == c
127 == 0x7F
b == c
128 == 0x80
-128 == c
128 == (c&0xFF)

posted @ 2007-07-17 23:22 Job Hu 阅读(281) | 评论 (0)编辑 收藏

2007年7月9日

Java Language Keywords

Here's a list of keywords in the Java programming language. You cannot use any of the following as identifiers in your programs. The keywords const and goto are reserved, even though they are not currently used. true, false, and null might seem like keywords, but they are actually literals; you cannot use them as identifiers in your programs.
abstract continue for new switch
assert*** default goto* package synchronized
boolean do if private this
break double implements protected throw
byte else import public throws
case enum**** instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp** volatile
const* float native super while

posted @ 2007-07-09 22:38 Job Hu 阅读(194) | 评论 (1)编辑 收藏

2007年5月30日

Tomcat笔记(三)

来看看ContainerBasestart方法:
 1public synchronized void start() throws LifecycleException {
 2
 3        //如果Container已经处于start状态,直接返回
 4        if (started) {
 5            if(log.isInfoEnabled())
 6                log.info(sm.getString("containerBase.alreadyStarted", logName()));
 7            return;
 8        }

 9        
10        // Notify our interested LifecycleListeners
11        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
12
13        started = true;
14
15        // Start our subordinate components, if any
16        if ((loader != null&& (loader instanceof Lifecycle))
17            ((Lifecycle) loader).start();
18        logger = null;
19        getLogger();
20        if ((logger != null&& (logger instanceof Lifecycle))
21            ((Lifecycle) logger).start();
22    //用来管理session
23        if ((manager != null&& (manager instanceof Lifecycle))
24            ((Lifecycle) manager).start();
25    //看名字就知道是干什么的,不过研究集群的优先级很低
26        if ((cluster != null&& (cluster instanceof Lifecycle))
27            ((Lifecycle) cluster).start();
28    //用来进行访问控制,或者权限控制的
29        if ((realm != null&& (realm instanceof Lifecycle))
30            ((Lifecycle) realm).start();
31    //和JNDI相关
32        if ((resources != null&& (resources instanceof Lifecycle))
33            ((Lifecycle) resources).start();
34
35        //启动所有子container
36        Container children[] = findChildren();
37        for (int i = 0; i < children.length; i++{
38            if (children[i] instanceof Lifecycle)
39                ((Lifecycle) children[i]).start();
40        }

41
42        // 启动Container内部持有的pipeline对象,Container对Pipeline接口的实现就是通过调用这个内部持有的Pipeline对象
43        if (pipeline instanceof Lifecycle)
44            ((Lifecycle) pipeline).start();
45
46        // Notify our interested LifecycleListeners
47        lifecycle.fireLifecycleEvent(START_EVENT, null);
48
49        // 注释说这个函数用来check session是否过期,但看的不是太懂
50        threadStart();
51
52        // Notify our interested LifecycleListeners
53        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
54
55}

56
 

所有和clusterrealm相关都放在最后来研究了,不管怎么样先把tomcat如何处理request的整个过程串起来对现在的我来说是最重要的。另外还有Tomcat中的很多部件都用到了JMX API,即SNMPJava实现来进行性能检测和管理,这个也会放在最后研究。

ContainerBase就看这么多了,下面来看看StandardEngine这个类。除去和clusterrealmJMX相关的方法后,StanderdEngine剩下的方法就很很少了。

StandardEngine有一个Service类型的成员。Java doc中指出Service就是由很多共享同一个ContainerConnector组成。一个Service对应于一个Container,来自这个Service的任何一个Connectorrequest都会由其对应的Container进行处理。看到现在的感觉就是ConnectorContainer提供request对象,并接受Container返回的response对象。在Tomcat中有很多类别都被用来体现现request或者response,例如org.apache.catalina.connector .Request就是Coyote request的一个wrapper类,Coyote这个framework帮助封装了底层的网络复杂性,向上提供一个统一的接口。我想tomcat既能够成为一个standalonehttpjsp/Servlet服务器,也能够同apache http server集成,很可能就是依赖于Coyote提供的统一接口。

在构造函数中会将StandardEngine这个Pipeline的最后一个Valve,即Basic设置为StandardEngineValve。来看看StandardEnginValueinvoke方法
 1public final void invoke(Request request, Response response)
 2        throws IOException, ServletException {
 3
 4        // Select the Host to be used for this Request
 5        Host host = request.getHost();
 6        if (host == null{
 7            response.sendError
 8                (HttpServletResponse.SC_BAD_REQUEST,
 9                 sm.getString("standardEngine.noHost"
10                              request.getServerName()));
11            return;
12        }

13
14        // Ask this Host to process this request
15        host.getPipeline().getFirst().invoke(request, response);
16
17    }

18
 

可以看出在处理到StandardEngine这个Pipeline的最后一个Valve时,会根据当前request所指定的Host,将当前的requestresponse传递给该Host这个Pipeline的第一个Valve进行处理。

我想Tomcat中的EngineHostContextWrapper处理request生成response的过程大概是这样的:

Engine在收到request后在其Pipeline中的每一个Valverequest进行处理,也可能会生成response的某些部分,在最后一个Valve中将requestresponse传给下一级ContainerHost的第一个ValveHost重复同样过程,继续传递给ContextContext再传递给Wrapper。由于Wrapper代表的是Servlet对象,因此在Wrapper处所有的处理都结束了,response对象生成完毕。当然了,如果在某一级中无法找到request要求的下一级对象,则整个处理过程也会立即结束。

posted @ 2007-05-30 22:58 Job Hu 阅读(352) | 评论 (1)编辑 收藏

2007年5月28日

Tomcat笔记(二)

ContainerBasePipeline接口的实现完全依赖于其内部的一个Pipeline类型的成员pipeline(实现类为StandardPipeline)。
   
Tomcatdoc中这样介绍Pipeline接口:该接口的invoke()方法被调用时,将会引发一系列Value对象的序列调用。要求一个Pipeline中的存在一个Value对象(多为最后一个Value对象)完成对request的处理,并生成相应的response,而不能试图将Request继续传递给其它Value对象(这个Value对象被称为Basic)。通常,每个Container对象都持有一个Pipline类型(实际上为StandardPipeline)的成员。在Pipelinedoc中,方法getBasicgetFirst两个方法的Method Summary完全一样,Apache的牛人们也不能免俗啊。

StandardPipeline除实现Pipeline接口外,也实现了Lifecycle接口。这个类的startstop方法,首先检查是否已经被startstop,如果是则会抛出一个LifecycleException的异常,否则便fire和生命期改变的相关事件,并调用其内部valve对象(如果该valve对象也实现了Lifecycle接口)的startstop方法。addValve方法用来向StandardPipeline中加入Valve对象,新加入的Value对象被放在一个叫做Basic的特殊Valve(就是一个Pipeline的最后一个Valve)的前面,如果在添加Valve的时候该StandardPipeline已经处于start状态,则会进行一些注册(调用apache commons库的一个类,完全没有看懂这个地方是什么作用>_<

posted @ 2007-05-28 07:39 Job Hu 阅读(300) | 评论 (0)编辑 收藏

2007年5月15日

一个简化的java线程池示例

//以前写在blogger上的一篇老文了
曾经很好奇线程池是怎么实现的,.net中有现成的线程池可以使用,但是java中没有。还有就是Servlet的service方法是怎么样为每一个 Request在不同的线程中独立服务的,由于Servlet接口没有继承自Runnable接口,因此无法直接由一个Servlet对象生成多个线程。后来在网上找到了一个java版本的线程池的例子(http://www.informit.com/articles/article.asp?p= 30483&seqNum=1&rl=1)在该例子的基础上简化得到了下面这个版本的java线程池,记录在这里。
*******************
ThreadPool.java
*******************

package threadPool;

import java.util.ArrayList;
import java.util.Collection;

public class ThreadPool
{
    Thread[] threadArray;
    Collection
<Runnable> jobs = new ArrayList<Runnable>();
 
    
public ThreadPool(int threadNum)
    
{
        threadArray 
= new WorkerThread[threadNum];
        
for (Thread thread : threadArray)
        
{
            thread 
= new WorkerThread();
            thread.start();
        }

    }

 
    
public synchronized void addJob(Runnable job)
    
{
        jobs.add(job);
        notify();
    }

 
    
private synchronized Runnable getJob()
    
{
        
while(jobs.isEmpty())
        
{
            
try
            
{
                wait();
            }
 catch (InterruptedException e)
            
{
                e.printStackTrace();
            }

        }

        Runnable job 
=  jobs.iterator().next();
        jobs.remove(job);
        
return job;
    }

    
    
private class WorkerThread extends Thread
    
{
        
public void run()
        
{
            Runnable job 
= null;
            
while(job == null)
            
{
                job 
= getJob();
                
if(job != null)
                
{
                    job.run();
                }

                job 
= null;
            }

       }

    }

}


 

*******************
ThreadPoolTest.java
*******************

package threadPool;

public class ThreadTest
{
    
private static class PrintClass implements Runnable
    
{
        
private int threadNo;
  
        
public PrintClass(int threadNo)
        
{
            
this.threadNo = threadNo;
        }

        
        
public void run()
        
{
            
for(int i = 0; i < 10; i++)
            
{
                
synchronized (System.out)
                
{
                    System.out.println(
"Thread "+threadNo+""+i);
                }

                
try
                
{
                    Thread.sleep(
1000);
                }
 catch (InterruptedException e)
                
{
                    e.printStackTrace();
                }

            }

        }
 
    }

 
    
public static void main(String[] args)
    
{
        ThreadPool tp 
= new ThreadPool(3);
        
for(int i=0; i <10; i++)
        
{
            tp.addJob(
new PrintClass(i));
        }

        
synchronized (System.out)
        
{
            System.out.println(
"Job adding finished");
        }

    }

}

posted @ 2007-05-15 12:53 Job Hu 阅读(898) | 评论 (3)编辑 收藏

2007年4月25日

Tomcat笔记(一)

包org.apache.catalina主要由接口组成。我们可以把这些接口分为几个大类。

第一类接口主要是对web application及其各个组成部分的抽象。这些接口以Container为父接口,分别为Context,Engine,Host,Wrapper。

Engine代表的是整个Catalina Servlet引擎。

Host代表的是Catalina Servlet引擎中的一个虚拟主机。

Context

Wrapper代表的是某一个具体的servlet

下面我从Container的抽象实现ContainerBase来切入Container,Context,Engine,Host,Wrapper的实现。

由于Container接口是web application中各部分的抽象的公共部分,因此其实现类ContrainerBase是一个抽象类。对于Container接口的各个子接口的实现类,则通过继承ContainerBase来实现接口Container接口。例如Engine接口继承Container接口,Engine的实现类StandardEnginer继承ContainerBase类。

ContainerBase实现得接口有Container,Lifecycle,MBeanRegistration, Pipeline,Serializable。其中Lifecycle,Pipeline和Container属于同一个包。

Lifecycle接口定义了一个具有生命期属性的组件所必须提供的方法:start(启动一个组件),stop(停止一个组件);除此之外该接口还定义了与具有生命期属性的组件的Listener相关的3个方法,用来添加、删除、查找对该组件的生命期阶段变化感兴趣的Listener。

Pipeline在Tomcat中是一个或者多个Value的组合,Value用来对Request进行处理,生成Response或者将Request和Response传给下一个Value进行处理。Tomcat并没有象通常一样将Pipeline和Value作为同一个接口,即使用Composite模式,而是Pipeline和Value分别作为集合和元素,Pipeline只能加入Value而不能加入Pipeline,Value则不能包含任何子Value。

ContainerBase对lifecycle接口的实现分为两类,addLifecycleListener、findLifecycleListener、removeLifecycleListener都是通过调用ContainerBase的一个LifecycleSupport成员实现;start和stop方法则为ContainerBase自己实现。我一开始以为LifecycleSupport也实现了lifecycle接口,但实际上并不是这样,原因是start和stop方法与具体的组件密切相关。此外LifecycleSupport中还包括一个名为fireLifecycleEvent的方法,该方法遍历所有的LifeCycleListener,并触发Lifecycle事件。总体上看LifecycleSupport实现了所有实现Lifecycle接口的组件的公共部分,维护一个LifecycleListener的数组,提供了添加、修改、获取LifecycleListener和触发各个Listener的方法。一个有趣的情况是,LifecycleSupport是一个final类,无法被继承,利用java的语言性质强制执行了面向对象中组合优于继承的思想。

posted @ 2007-04-25 22:21 Job Hu 阅读(342) | 评论 (1)编辑 收藏