面试总结

0.Java 中多线程同步是什么?

在多线程程序下,同步能控制对共享资源的访问。如果没有同步,当一个 Java 线程在修改一个共享变量时,另外一个线程正在使用或者更新同一个变量,这样容易导致程序出现错误的结果。

1.解释实现多线程的几种方法?

Java 线程可以实现 Runnable 接口或者继承 Thread 类来实现,当你打算多重继承时,优先选择实现 Runnable

2.Thread.start () Thread.run ()有什么区别?

Thread.start ()方法(native)启动线程,使之进入就绪状态,当 cpu 分配时间该线程时,由 JVM 调度执行 run ()方法。

3.为什么需要 run () start ()方法,我们可以只用 run ()方法来完成任务吗?

我们需要 run ()&start ()这两个方法是因为 JVM 创建一个单独的线程不同于普通方法的调用,所以这项工作由线程的 start 方法来完成,start 由本地方法实现,需要显示地被调用,使用这俩个方法的另外一个好处是任何一个对象都可以作为线程运行,只要实现了 Runnable 接口,这就避免因继承了 Thread 类而造成的 Java 的多继承问题。

4.什么是 ThreadLocal 类,怎么使用它?

ThreadLocal 是一个线程级别的局部变量,并非本地线程ThreadLocal 为每个使用该变量的线程提供了一个独立的变量副本,每个线程修改副本时不影响其它线程对象的副本(译者注)

下面是线程局部变量(ThreadLocal variables)的关键点:

一个线程局部变量(ThreadLocal variables)为每个线程方便地提供了一个单独的变量。

ThreadLocal 实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联一个线程。

当多个线程访问 ThreadLocal 实例时,每个线程维护 ThreadLocal 提供的独立的变量副本。

常用的使用可在 DAO 模式中见到,当 DAO 类作为一个单例类时,数据库链接(connection)被每一个线程独立的维护,互不影响。(基于线程的单例)

ThreadLocal 难于理解,下面这些引用连接有助于你更好的理解它。

Good article on ThreadLocal on IBM DeveloperWorks 》、《理解 ThreadLocal》、《Managing data : Good example》、《Refer Java API Docs

5.什么时候抛出 InvalidMonitorStateException 异常,为什么?

调用 wait ()/notify ()/notifyAll ()中的任何一个方法时,如果当前线程没有获得该对象的锁,那么就会抛出 IllegalMonitorStateException 的异常(也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用 wait ()/notify ()/notifyAll ())。由于该异常是 RuntimeExcpetion 的子类,所以该异常不一定要捕获(尽管你可以捕获只要你愿意).作为 RuntimeException,此类异常不会在 wait (),notify (),notifyAll ()的方法签名提及。

6.Sleep ()suspend () wait ()之间有什么区别?

Thread.sleep ()使当前线程在指定的时间处于非运行Not Runnable)状态。线程一直持有对象的监视器。比如一个线程当前在一个同步块或同步方法中,其它线程不能进入该块或方法中。如果另一线程调用了 interrupt ()方法,它将唤醒那个睡眠的线程。

注意:sleep ()是一个静态方法。这意味着只对当前线程有效,一个常见的错误是调用t.sleep (),(这里的t是一个不同于当前线程的线程)。即便是执行t.sleep (),也是当前线程进入睡眠,而不是t线程。t.suspend ()是过时的方法,使用 suspend ()导致线程进入停滞状态,该线程会一直持有对象的监视器,suspend ()容易引起死锁问题。

object.wait ()使当前线程出于不可运行状态,和 sleep ()不同的是 wait object 的方法而不是 thread。调用 object.wait ()时,线程先要获取这个对象的对象锁,当前线程必须在锁对象保持同步,把当前线程添加到等待队列中,随后另一线程可以同步同一个对象锁来调用 object.notify (),这样将唤醒原来等待中的线程,然后释放该锁。基本上 wait ()/notify () sleep ()/interrupt ()类似,只是前者需要获取对象锁。

7.在静态方法上使用同步时会发生什么事?

同步静态方法时会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。

8.当一个同步方法已经执行,线程能够调用对象上的非同步实例方法吗?

可以,一个非同步方法总是可以被调用而不会有任何问题。实际上,Java 没有为非同步方法做任何检查,锁对象仅仅在同步方法或者同步代码块中检查。如果一个方法没有声明为同步,即使你在使用共享数据 Java 照样会调用,而不会做检查是否安全,所以在这种情况下要特别小心。一个方法是否声明为同步取决于临界区访问(critial section access),如果方法不访问临界区(共享资源或者数据结构)就没必要声明为同步的。

下面有一个示例说明:Common 类有两个方法 synchronizedMethod1() method1()MyThread 类在独立的线程中调用这两个方法。

1.public class Common {  

2.   

3.public synchronized void synchronizedMethod1() {  

4.System.out.println ("synchronizedMethod1 called");  

5.try {  

6.Thread.sleep (1000);  

7.} catch (InterruptedException e) {  

8.e.printStackTrace ();  

9.}  

10.                            System.out.println ("synchronizedMethod1 done");  

11.                            }  

12.                            public void method1() {  

13.                            System.out.println ("Method 1 called");  

14.                            try {  

15.                            Thread.sleep (1000);  

16.                            } catch (InterruptedException e) {  

17.                            e.printStackTrace ();  

18.                            }  

19.                            System.out.println ("Method 1 done");  

20.                            }  

21.                           

1.public class MyThread extends Thread {  

2.private int id = 0;  

3.private Common common;  

4.   

5.public MyThread (String name, int no, Common object) {  

6.super(name);  

7.common = object;  

8.id = no;  

9.}  

10.                               

11.                            public void run () {  

12.                            System.out.println ("Running Thread" + this.getName ());  

13.                            try {  

14.                            if (id == 0) {  

15.                            common.synchronizedMethod1();  

16.                            } else {  

17.                            common.method1();  

18.                            }  

19.                            } catch (Exception e) {  

20.                            e.printStackTrace ();  

21.                            }  

22.                            }  

23.                               

24.                            public static void main (String[] args) {  

25.                            Common c = new Common ();  

26.                            MyThread t1 = new MyThread ("MyThread-1", 0, c);  

27.                            MyThread t2 = new MyThread ("MyThread-2", 1, c);  

28.                            t1.start ();  

29.                            t2.start ();  

30.                            }  

31.                            }  

这里是程序的输出:

1.Running ThreadMyThread-1  

2.synchronizedMethod1 called  

3.Running ThreadMyThread-2  

4.Method 1 called  

5.synchronizedMethod1 done  

6.Method 1 done 

 

结果表明即使 synchronizedMethod1()方法执行了,method1()也会被调用。

9.在一个对象上两个线程可以调用两个不同的同步实例方法吗?

不能,因为一个对象已经同步了实例方法,线程获取了对象的对象锁。所以只有执行完该方法释放对象锁后才能执行其它同步方法。看下面代码示例非常清晰:Common 类有 synchronizedMethod1() synchronizedMethod2()方法,MyThread 调用这两个方法。

1.public class Common {  

2.public synchronized void synchronizedMethod1() {  

3.System.out.println ("synchronizedMethod1 called");  

4.try {  

5.Thread.sleep (1000);  

6.} catch (InterruptedException e) {  

7.e.printStackTrace ();  

8.}  

9.System.out.println ("synchronizedMethod1 done");  

10.                            }  

11.                               

12.                            public synchronized void synchronizedMethod2() {  

13.                            System.out.println ("synchronizedMethod2 called");  

14.                            try {  

15.                            Thread.sleep (1000);  

16.                            } catch (InterruptedException e) {  

17.                            e.printStackTrace ();  

18.                            }  

19.                            System.out.println ("synchronizedMethod2 done");  

20.                            }  

21.                           

1.public class MyThread extends Thread {  

2.private int id = 0;  

3.private Common common;  

4.   

5.public MyThread (String name, int no, Common object) {  

6.super(name);  

7.common = object;  

8.id = no;  

9.}  

10.                               

11.                            public void run () {  

12.                            System.out.println ("Running Thread" + this.getName ());  

13.                            try {  

14.                            if (id == 0) {  

15.                            common.synchronizedMethod1();  

16.                            } else {  

17.                            common.synchronizedMethod2();  

18.                            }  

19.                            } catch (Exception e) {  

20.                            e.printStackTrace ();  

21.                            }  

22.                            }  

23.                               

24.                            public static void main (String[] args) {  

25.                            Common c = new Common ();  

26.                            MyThread t1 = new MyThread ("MyThread-1", 0, c);  

27.                            MyThread t2 = new MyThread ("MyThread-2", 1, c);  

28.                            t1.start ();  

29.                            t2.start ();  

30.                            }  

31.                           

10.什么是死锁

死锁就是两个或两个以上的线程被无限的阻塞,线程之间相互等待所需资源。这种情况可能发生在当两个线程尝试获取其它资源的锁,而每个线程又陷入无限等待其它资源锁的释放,除非一个用户进程被终止。就 JavaAPI 而言,线程死锁可能发生在一下情况。

·             当两个线程相互调用 Thread.join ()

·             当两个线程使用嵌套的同步块,一个线程占用了另外一个线程必需的锁,互相等待时被阻塞就有可能出现死锁。

11.什么是线程饿死,什么是活锁?

线程饿死和活锁虽然不想是死锁一样的常见问题,但是对于并发编程的设计者来说就像一次邂逅一样。

当所有线程阻塞,或者由于需要的资源无效而不能处理,不存在非阻塞线程使资源可用。JavaAPI 中线程活锁可能发生在以下情形:

·             当所有线程在程序中执行 Object.wait (0),参数为 0 wait 方法。程序将发生活锁直到在相应的对象上有线程调用 Object.notify ()或者 Object.notifyAll ()

·             当所有线程卡在无限循环中。

Java程序员应该了解的10个面向对象设计原则

原则1DRYDon't repeat yourself

即不要写重复的代码,而是用“abstraction”类来抽象公有的东西。如果你需要多次用到一个硬编码值,那么可以设为公共常量;如果你要在两个以上的地方使用一个代码块,那么可以将它设为一个独立的方法。SOLID设计原则的优点是易于维护,但要注意,不要滥用,duplicate 不是针对代码,而是针对功能。这意味着,即使用公共代码来验证OrderIDSSN,二者也不会是相同的。使用公共代码来实现两个不同的功能,其实就是近似地把这两个功能永远捆绑到了一起,如果OrderID改变了其格式,SSN验证代码也会中断。因此要慎用这种组合,不要随意捆绑类似但不相关的功能。

原则2:封装变化

在软件领域中唯一不变的就是“Change”,因此封装你认为或猜测未来将发生变化的代码。OOPS设计模式的优点在于易于测试和维护封装的代码。如果你使用Java编码,可以默认私有化变量和方法,并逐步增加访问权限,比如从privateprotectednot public。有几种Java设计模式也使用封装,比如Factory设计模式是封装对象创建,其灵活性使得之后引进新代码不会对现有的代码造成影响。

原则3:开闭原则

即对扩展开放,对修改关闭。这是另一种非常棒的设计原则,可以防止其他人更改已经测试好的代码。理论上,可以在不修改原有的模块的基础上,扩展功能。这也是开闭原则的宗旨。

原则4:单一职责原则

类被修改的几率很大,因此应该专注于单一的功能。如果你把多个功能放在同一个类中,功能之间就形成了关联,改变其中一个功能,有可能中止另一个功能,这时就需要新一轮的测试来避免可能出现的问题。

原则5:依赖注入或倒置原则

这个设计原则的亮点在于任何被DI框架注入的类很容易用mock对象进行测试和维护,因为对象创建代码集中在框架中,客户端代码也不混乱。有很多方式可以实现依赖倒置,比如像AspectJ等的AOPAspect Oriented programming)框架使用的字节码技术,或Spring框架使用的代理等。

原则6:优先利用组合而非继承

如果可能的话,优先利用组合而不是继承。一些人可能会质疑,但我发现,组合比继承灵活得多。组合允许在运行期间通过设置类的属性来改变类的行为,也可以通过使用接口来组合一个类,它提供了更高的灵活性,并可以随时实现。Effective Java也推荐此原则。

原则7:里氏代换原则(LSP

根据该原则,子类必须能够替换掉它们的基类,也就是说使用基类的方法或函数能够顺利地引用子类对象。LSP原则与单一职责原则和接口分离原则密切相关,如果一个类比子类具备更多功能,很有可能某些功能会失效,这就违反了LSP原则。为了遵循该设计原则,派生类或子类必须增强功能。

原则8:接口分离原则

采用多个与特定客户类有关的接口比采用一个通用的涵盖多个业务方法的接口要好。设计接口很棘手,因为一旦释放接口,你就无法在不中断执行的情况下改变它。在Java中,该原则的另一个优势在于,在任何类使用接口之前,接口不利于实现所有的方法,所以单一的功能意味着更少的实现方法。

原则9:针对接口编程,而不是针对实现编程

该原则可以使代码更加灵活,以便可以在任何接口实现中使用。因此,在Java中最好使用变量接口类型、方法返回类型、方法参数类型等。《Effective Java和《head first design pattern》书中也有提到。

原则10:委托原则

该原则最典型的例子是Java中的equals() hashCode() 方法。为了平等地比较两个对象,我们用类本身而不是客户端类来做比较。这个设计原则的好处是没有重复的代码,而且很容易对其进行修改。

总之,希望这些面向对象的设计原则能帮助你写出更灵活更好的代码。理论是第一步,更重要的是需要开发者在实践中去运用和体会。

Java堆内存(heap memory)的十个要点:

1. Java堆内存是操作系统分配给JVM的内存的一部分。

2. 当我们创建对象时,它们存储在Java堆内存中。

3. 为了便于垃圾回收,Java堆空间分成三个区域,分别叫作New Generation, Old Generation或叫作Tenured Generation,还有Perm Space

4. 你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。不要忘了在大小后面加上”M”或者”G”来表示单位。举个例子,你可以用 -Xmx256m来设置堆内存最大的大小为256MB

5. 你可以用JConsole或者 Runtime.maxMemory(), Runtime.totalMemory(), Runtime.freeMemory()来查看Java中堆内存的大小。

6. 你可以使用命令“jmap”来获得heap dump,用“jhat”来分析heap dump

7. Java堆空间不同于栈空间,栈空间是用来储存调用栈和局部变量的。

8. Java垃圾回收器是用来将死掉的对象(不再使用的对象)所占用的内存回收回来,再释放到Java堆空间中。

9. 当你遇到java.lang.outOfMemoryError时,不要紧张,有时候仅仅增加堆空间就可以了,但如果经常出现的话,就要看看Java程序中是不是存在内存泄露了。

10. 请使用ProfilerHeap dump分析工具来查看Java堆空间,可以查看给每个对象分配了多少内存。

Struts和spring分别是什么?

Struts只是一个MVC框架(Framework),用于快速开发Java Web应用。Struts实现的重点在C(Controller),包括ActionServlet/RequestProcessor和我们定制的Action,也为V(View)提供了一系列定制标签(Custom Tag)。但Struts几乎没有涉及M(Model),所以Struts可以采用JAVA实现的任何形式的商业逻辑。

Spring是一个轻型容器(light-weight container),其核心是Bean工厂(Bean Factory),用以构造我们所需要的M(Model)。在此基础之上,Spring提供了AOP(Aspect-Oriented Programming, 面向层面的编程)的实现,用它来提供非管理环境下申明方式的事务、安全等服务;对Bean工厂的扩展ApplicationContext更加方便我们实现J2EE的应用;DAO/ORM的实现方便我们进行数据库的开发;Web MVC和Spring Web提供了Java Web应用的框架或与其他流行的Web框架进行集成。

就是说可将两者一起使用,达到将两者自身的特点进行互补。

spring struts hibernate分别怎么描述

struts负责调度分发请求到相应的处理方法页面上.主要起到控制的作用.

hibernate属于DAO,可以更简单的对数据库操作.

spring有粘合的作用,明确依赖关系.也就是业务逻辑的一个大工厂.为业务逻辑对象自动的NEW.

Struts、spring、hibernate、EJB、ant分别是什么?

Struts只是一个MVC框架(Framework),用于快速开发Java Web应用。Struts实现的重点在C(Controller),包括ActionServlet/RequestProcessor和我们定制的Action,也为V(View)提供了一系列定制标签(Custom Tag)。但Struts几乎没有涉及M(Model),所以Struts可以采用JAVA实现的任何形式的商业逻辑。

 

Spring

 

Spring是一个轻型容器(light-weight container),其核心是Bean工厂(Bean Factory),用以构造我们所需要的M(Model)。在此基础之上,Spring提供了AOP(Aspect-Oriented Programming, 面向层面的编程)的实现,用它来提供非管理环境下申明方式的事务、安全等服务;对Bean工厂的扩展ApplicationContext更加方便我们实现J2EE的应用;DAO/ORM的实现方便我们进行数据库的开发;Web MVC和Spring Web提供了Java Web应用的框架或与其他流行的Web框架进行集成。

就是说可将两者一起使用,达到将两者自身的特点进行互补。

 

Hibernate

 

Hibernate是一个免费的开源Java包,它使得与关系数据库打交道变得十分轻松,就像您的数据库中包含每天使用的普通Java对象一样,同时不必考虑如何把它们从神秘的数据库表中取出(或放回到数据库表中)。它解放了您,使您可以专注于应用程序的对象和功能,而不必担心如何保存它们或稍后如何找到它们。

 

EJB

 

一个技术规范:EJB 从技术上而言不是一种"产品"

EJB 是一种标准描述了构建应用组件要解决的:

可扩展 (Scalable)

分布式 (Distributed)

事务处理 (Transactional)

数据存储 (Persistent)

安全性 (Secure)

 

ANT

 

-. Ant简介

Ant是一个类似make的工具,用来编译/运行/测试java程序。

构建、包装和发布过程中几乎每一件事都可以由Ant的任务来处理.

 

二.Ant的安装及配置

你可以从Jakata网站下载预编译的ANT,解压至任一目录;

设置自己的环境变量,即ANT_HOME,指向解压目录;

设置JAVA_HOME环境变量,指向jdk的根目录;

 

三:用ant管理项目

 

Ant一启动就会自动地加载一个叫做Build.xml的项目配置文件。如果想给这个项目配置文件取别的名字,你可以使用buildfile标记来运行ant,就像下面这样:

ant -buildfile Project_configuration.xml

主要特点:

使用xml文件作为配置文件,即build.xml;

可与junit作无缝整合,达到系统测试、编译到发布的功能;

强大、详细的报表功能;

控制灵活,可自定义要执行的任务组合。

J2EE框架(Struts&Hibernate&Spring)的理解

Struts(表示层)+Spring(业务层)+Hibernate(持久层)

Struts:Struts是一个表示层框架,主要作用是界面展示,接收请求,分发请求。

在MVC框架中,Struts属于VC层次,负责界面表现,负责MVC关系的分发。(View:沿用JSP,HTTP,Form,Tag,Resourse ;Controller:ActionServlet,struts-config.xmlAction)

Hibernate:Hibernate是一个持久层框架,它只负责与关系数据库的操作。

Spring:Spring是一个业务层框架,是一个整合的框架,能够很好地黏合表示层与持久层。

2EE是一个基于多层开发的java平台;能够开发BS的应用程序;使用J2EE开发应用程序通常分为 : 客户端 - 表现层 - 业务服务层 - 持久层 - 数据层其中客户端层不需要程序员开发,每一个浏览器都可以作为客户端层表现层的技术包括JSP,servlet,以及struts、JSF等框架;由于表现层是J2EE中和客户端打交道的前端层,所以struts在J2EE中的作用主要是控制客户请求的走向(请求应该由哪个业务Action执行)以及为客户提供视图。

业务服务层的技术包括EJB,spring等框架;顾名思义,这个层的功能是提供业务逻辑(整个系统的核心,也就是增删改查操作)和系统级服务(事务、异常、权限、安全、日志等),而spring的作用就是管理这些业务对象和服务对象,通过spring的IOC技术对他们实现松耦合的隔离。同时,spring虽然是业务服务层的框架,但是他的功能并不局限在这一个层,spring开发初期致力于解决传统J2EE开发的困难性而设计,从表现层到持久层,spring都有涉足;在表现层方面,提供了自己的MVC框架;但是spring并不是替代J2EE中已有的框架,spring的精华之处在于和其他框架实现无缝整合。比如在SSH中,通过spring管理struts的业务逻辑Action和Hibernate的DAO对象

持久层的技术包括JDBC,Hibernate等框架;持久层,也就是将对象进行持久化到数据库中;传统的持久化方式JDBC由于是一种面向对象设计语言,在访问关系型数据库(mysql,Oracle)上有很大的缺陷(需要手动将数据库表转化为java对象), Hibernate的出现很大程度上解决了这个问题,HIbernate是一个对象关系映射工具,通过在java对象和数据库表之间建立映射关系(一个xml 类型的mapping文件),把对数据库表的操作转化为对java对象的操作。大大减低了编程的复杂性。

1flex通常是指Adobe Flex,是最初由Macromedia公司在20043月发布的,基于其专有的Macromedia Flash平台,它是涵盖了支持RIARich Internet Applications)的开发和部署的一系列技术组合。flex的另一个意思是一款生成扫描器的工具,能够识别文本中的词法模式。Flex 是一个高效、免费的开源框架,可用于构建具有表现力的 Web 应用程序,这些应用程序利用 Adobe Flash Player Adobe AIR, 运行时跨浏览器、桌面和操作系统实现一致的部署。

2iBATIS提供的持久层框架包括SQL MapsData Access ObjectsDAO),同时还提供一个利用这个框架开发的JPetStore实例。iBATIS就是我们通常所说的数据映射器(data mapper.所谓映射器,是用于在对象和数据库之间搬运数据,同时保证对象、数据库以及映射器本身都相互独立。每个框架都是建立在一定的规则和约束之上的。底层的框架,如JDBC,提供了一个灵活且完备的功能集合,但是它们使用起来却更难也更繁琐。高层的框架,如对象/关系映射工具,使用就更加方便并且可以帮你节省大量工作,但是它们是建立在更多的假设和约束的基础上的,这使得它们只能适用于较少的应用。iBATIS是一个中层的框架。它比JDBC更高层一些,但是相对于对象/关系映射工具,又要更底层一些。这使得iBATIS处于一个很独特的位置上,使它能够适用于一些

较为特别的应用。在本书前面的部分,我们讨论了为什么iBATIS对于多种应用类型都是有用的,包括小的桌面应用,和较大的、企业级的Web应用——

以及任何介于这两者之间的应用类型。那么,iBATIS不适用的场合是什么呢?下面几节就将详细描述不适合使用iBATIS的各种情况,并且给出有关替代方案的建议。

3uml:

1.最常用的UML图包括:用例图、类图、序列图、状态图、活动图、组件图和部署图。

2.用例图的主要目的是帮助开发团队以一种可视化的方式理解系统的功能需求,包括基于基本流程的"角色"actors,也就是与系统交互的其他实体)关系,以及系统内用例之间的关系。

3.序列图有两个维度:垂直维度以发生的时间顺序显示消息/调用的序列;水平维度显示消息被发送到的对象实例。

4.状态图表示某个类所处的不同状态和该类的状态转换信息。有人可能会争论说每个类都有状态,但不是每个类都应该有一个状态图。只对"感兴趣的"状态的类(也就是说,在系统活动期间具有三个或更多潜在状态的类)才进行状态图描述。

5.组件图提供系统的物理视图。它的用途是显示系统中的软件对其他软件组件(例如,库函数)的依赖关系。进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源. 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

2、进程和线程的区别在于:

简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

 

Struts1Struts2的区别和对比:

Action
:
• Struts1
要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。
• Struts 2 Action
类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2Action对象。

线程模式:
• Struts1 Action
是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
• Struts2 Action
对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)

Servlet
依赖:
• Struts1 Action
依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest HttpServletResponse 被传递给execute方法。
• Struts 2 Action
不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的requestresponse。但是,其他的元素减少或者消除了直接访问HttpServetRequest HttpServletResponse的必要性。

可测性:
测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套Struts1的模拟对象(来进行测试)。
• Struts 2 Action
可以通过初始化、设置属性、调用方法来测试,依赖注入支持也使测试更容易。

捕获输入:
• Struts1
使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。动态BeanDynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有冗余的javabean)。
• Struts 2
直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己()属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglibPOJO输入对象的引用。

表达式语言:
• Struts1
整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合和索引属性的支持很弱。
• Struts2
可以使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL).

绑定值到页面(view:
• Struts 1
使用标准JSP机制把对象绑定到页面中来访问。
• Struts 2
使用 "ValueStack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。

类型转换:
• Struts 1 ActionForm
属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
• Struts2
使用OGNL进行类型转换。提供基本和常用对象的转换器。

校验:
• Struts 1
支持在ActionFormvalidate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
• Struts2
支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性

Action
执行的控制:
• Struts1
支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
• Struts2
支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。

OOB - 带外数据

传输层协议使用带外数据(out-of-band,OOB)来发送一些重要的数据, 如果通信一方有重要的数据需要通知对方时,协议能够将这些数据快速地发送到对方.为了发送这些数据,协议一般不使用与普通数据相同的通道,而是使用另外的通道.linux系统的套接字机制支持低层协议发送和接受带外数据.但是TCP协议没有真正意义上的带外数据.为了发送重要协议,TCP提供了一种称为紧急模式(urgentmode)的机制.TCP协议在数据段中设置URG,表示进入紧急模式.接收方可以对紧急模式采取特殊的处理.很容易看出来,这种方式数据不容易被阻塞,可以通过在我们的服务器端程序里面捕捉SIGURG信号来及时接受数据或者使用带OOB标志的recv函数来接受.

 

Ajax优点:

v      减轻服务器的负担

v      无刷新更新页面

v      更好的用户体验

v      节约网络租用成本

v      使数据与呈现分离

 

1. 减轻服务器的负担。因为AJAX的根本理念是按需取数据,所以最大可能的减少了冗余请求和响应对服务器造成的负担;
2.
无刷新更新页面,减少用户实际和心理等待时间;
3.
更好的用户体验;
4.
也可以把以前的一些服务器负担的工作转嫁到客户端,利用客户端闲置的处理能力来处理,减轻服务器和网络的负担,节约网络租用成本;
5.
面向AOPWeb Services的应用;
6. Ajax
使WEB中的界面与应用分离(也可以说是数据与呈现分离);

Ajax 的不足缺点

v      用户浏览习惯的改变

v      Search engine难搜索到

v      破坏浏览器后退按钮的正常行为

v      性能问题,client端接受大量数据.

v      不支持智能终端设备。

v      开发难度的加大

Ajax的核心是JavaScript对象XmlHttpRequest。该对象在Internet Explorer 5中首次引入,它是一种支持异步请求的技术。简而言之,XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应,而不阻塞用户。

      AJAX工作的大致流程是这样的:首先由用户user在客户端browser页面端触发一个事件,比如说onblur事件,这个事件是能被Javascrīpt捕获到的。然后Javascrīpt相应的创建一个XMLHttpRequest请求,并通过XMLHttpRequest异步的把请求发送到服务器端,同时等待服务器端的响应。服务器端程序在接受请求后,着手处理并把结果返回,返回的结果被XMLHttpRequest捕获到并返回给Javascrīpt,再由Javascrīpt调用相应的DOM进行显示层的控制。

Cookie概述

l       cookie是浏览器提供的一种机制,它将document对象的cookie属性提供给javascript.可以有javascript对其进行控制,但并不是javascript本身的性质.

l       Cookie是存于用户硬盘的一个文件,这个文件通常对应一个域名,当浏览器再次访问该域名时,便使这个cookie可用.

Cookie的应用场合

1.保存用户登录状态

       例如将用户id存储于一个cookie,这样当用户下次访问该页面时就不需要重新登录了,很多论坛和社区都提供这样的功能.cookie还可以设置过期时间,当超过时间期限后,cookie会自动消失.因此,系统往往还可以提示用户保持登录状态的时间:常见选项有一个月、三个月、一年.

 

2.跟踪用户行为

       例如一个天气预报网站,能够根据用户选择的地区显示当地大的天气情况。如果每次都需要选择所在地是烦琐的,当利用cookie后就会显的很人性化,系统能够记住上一次访问的地区。

 

3.定制页面

       如果网站提供了换肤的功能,那么可以使用cookie来记录用户的选项。例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。

 

4.创建购物车

       类如jsp中的session功能。

什么是dwr?

n       DWR(Direct Web Remoting)是一个WEB远程调用框架.利用这个框架可以让AJAX开发变得很简单.利用DWR可以在客户端利用JavaScript直接调用服务端的Java方法并返回值给JavaScript,就好像Java方法直接暴露给本地客户端一样(DWR根据Java类来动态生成JavaScrip代码).

1.1 什么是JavaScript

JavaScriptWWW上的一种功能强大的编程语言,用于开发交互式的Web页面,它不仅可以直接应用于HTML文档以获得交互失效果或其他动态效果,而且可以运行于服务器端,从而替代传统的CGI程序。

         JavaScript的特点

l        是一种脚本语言

l        基于对象

l        安全性

l        跨平台性

         JavaScript的应用

l        客户端的应用

l        基于对象服务器应用

什么是XML

XML是一种可扩展标识语言,是一种简单的数据存储语言,使用一系列简单的标记描述数据,XML是一种跨平台的,与软、硬件无关的,处理信息的工具。

 

Hibernate是一个ORMapping的实现,所以主要功能是操作数据库,是以对象的形式操作数据库。

Hibernate是面向对象编程与关系型数据库之间的桥梁。

Hibernate优势:开源、成熟、流行、自定义API

Hibernate开发步骤

1..持久化类的设计(POJO)

2.持久化类和关系数据库的映射(HBM映射文件)

3.应用和开发

SessionFactory

n       应用程序从SessionFactory(会话工厂)里获得Session会话实例。它在多个应用线程间进行共享。通常,整个应用只有唯一的一个会话工厂,在应用初始化时被创建。如果使用Hibernate访问多个数据库,要对每一个数据库使用一个会话工厂。

n       SessionFactory对象建立后,则保存当前cfg的数据库配置信息和所有映射关系以及预定义的SQL语句

n       负责创建Session对象,可以通过Configuration对象创建SessionFactory对象

       Configuration cfg=new Configuration().configure();

       SessionFactory factory=cfg.buildSessionFactory();

n       Session不是线程安全的,它代表与数据库之间的一次操作。

n       Session也称为持久化管理器,因为它是与持久化有关的操作接口。

n       Session通过SessionFactory打开,在所有的工作完成后,需要关闭。

n       它与Web层的HttpSession没有任何关系。

n       Session对象定义了添加、更新、删除、查询等操作,是持久化操作的基础。其设计是非线程安全的。一个Session对象只可以由一个线程使用。

       Session对象可以由SessionFactory对象创建

       Configuration cfg=new Configuration().configure();

       SessionFactory factory=cfg.builddSessionFactory();

       Session session=factory.openSession();

Hibernate中的实体对象可以分为三种状态

Transient(临时状态)

Persistent(持久化状态)

Detached(脱管状态/游离状态)

Detached(脱管状态/游离状态)

Detached Objects

Session关闭之后,持久化对象变为detached对象。表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理

脏数据(dirty data):和数据库没有同步的数据

Hibernate分页

n       HibernateCriteria QueryQuery接口中提供以下两个方法,用于完成分页功能。   

       setFirstResult(2);

       下标从0开始,实际是从取第三条记录开始

       setMaxResults(2);

       2条记录,取第三条和第四条记录。

级联属性cascade

n       级联是指定两个对象之间的操作联动关系,对一个对象执行了操作之后,对其指定的级联对象也要执行相同的操作。

n       有以下取值:
all:
代表在所有的情况下都执行级联操作

       none:在所有情况下都不执行级联操作

       save-update:在保存和更新时执行级联操作

       delete:在删除时执行级联操作

n       inverse是关联关系的控制方向

n       cascade是操作上的连锁反应

 

flex通常是指Adobe Flex,是最初由Macromedia公司在20043月发布的,基于其专有的Macromedia Flash平台,它是涵盖了支持RIARich Internet Applications

的开发和部署的一系列技术组合。flex的另一个意思是一款生成扫描器的工具,能够识别文本中的词法模式。

Flex 是一个高效、免费的开源框架,可用于构建具有表现力的 Web 应用程序,这些应用程序利用 Adobe Flash Player Adobe AIR, 运行时跨浏览器、桌面和操作

系统实现一致的部署。

iBATIS提供的持久层框架包括SQL MapsData Access ObjectsDAO),同时还提供一个利用这个框架开发的JPetStore实例。

 

 iBATIS就是我们通常所说的数据映射器(data mapper.所谓映射器,是用于在对象和数据库之间搬运数据,同时保证对象、数据库以及映射器本身都相互独立。

 

 每个框架都是建立在一定的规则和约束之上的。底层的框架,如JDBC,提供了一个灵活且完备的功能集合,但是它们使用起来却更难也更繁琐。高层的框架,如

对象/关系映射工具,使用就更加方便并且可以帮你节省大量工作,但是它们是建立在更多的假设和约束的基础上的,这使得它们只能适用于较少的应用。

 

iBATIS是一个中层的框架。它比JDBC更高层一些,但是相对于对象/关系映射工具,又要更底层一些。这使得iBATIS处于一个很独特的位置上,使它能够适用于一些

较为特别的应用。在本书前面的部分,我们讨论了为什么iBATIS对于多种应用类型都是有用的,包括小的桌面应用,和较大的、企业级的Web应用——

以及任何介于这两者之间的应用类型。那么,iBATIS不适用的场合是什么呢?下面几节就将详细描述不适合使用iBATIS的各种情况,并且给出有关替代方案的建议。

memcached的特征

  memcached作为高速运行的分布式缓存服务器,具有以下的特点。

  ·协议简单

  ·基于libevent的事件处理

  ·内置内存存储方式

  · memcached不互相通信的分布式

协议简单

  memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。

因此,通过telnet也能在memcached上保存数据、取得数据。

uml:

1.最常用的UML图包括:用例图、类图、序列图、状态图、活动图、组件图和部署图。

2.用例图的主要目的是帮助开发团队以一种可视化的方式理解系统的功能需求,包括基于基本流程的"角色"actors,也就是与系统交互的其他实体)关系,以及系统内用例之间的关系。

3.序列图有两个维度:垂直维度以发生的时间顺序显示消息/调用的序列;水平维度显示消息被发送到的对象实例。

4.状态图表示某个类所处的不同状态和该类的状态转换信息。有人可能会争论说每个类都有状态,但不是每个类都应该有一个状态图。只对"感兴趣的"状态的类(也就是说,在系统活动期间具有三个或更多潜在状态的类)才进行状态图描述。

5.组件图提供系统的物理视图。它的用途是显示系统中的软件对其他软件组件(例如,库函数)的依赖关系。

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

 

线程是进程的一个实体,CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

 

一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

2、进程和线程的区别在于:

 

 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.

 

线程的划分尺度小于进程,使得多线程程序的并发性高。

 

另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。

 

线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

 

从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

Hibernate缓存分为二级,第一级存放于session中称为一级缓存,默认带有且不能卸载。第二级是由sessionFactory控制的进程级缓存。是全局共享的缓存,凡是会调用二级缓存的查询方

法都会从中受益。

只有经正确的配置后二级缓存才会发挥作用。同时在进行条件查询时必须使用相应的方法才能从缓存中获取数据。比如Query.iterate()方法、loadget方法等。必须注意的是session.find

方法永远是从数据库中获取数据,不会从二级缓存中获取数据,即便其中有其所需要的数据也是如此。

6.域名(Domain Name),是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置),目前域名已经成为互

联网的品牌、网上商标保护必备的产品之一。

你可能感兴趣的:(面试经验)