Tomcat中常见线程说明

本文讲述了Tomcat的常见线程的功能、名称、线程池和配置等信息,其中源码来自于Tomcat 6.0.18。

 

Work线程

 

功能

HTTP请求的处理线程(非NIO)。当有新的http请求进来后,则会从线程池中获得一个线程Work对象,调用Work.assign函数,将新到的http请求分配给这个线程。

名称

名称是http-[IpAddr]-[Port]-[Number],如http-0.0.0.0-8080-1

这个可以从Http11Protocol中的setName函数和Worker中的start方法得知这个命名方式。

public String getName() {
   String encodedAddr = "";
   if (getAddress() != null) {
       encodedAddr = "" + getAddress();
       if (encodedAddr.startsWith("/" ))
           encodedAddr = encodedAddr.substring(1);
       encodedAddr = URLEncoder. encode(encodedAddr) + "-";
   }
 
10    return ("http-" + encodedAddr + endpoint.getPort());
11 }
12  
13  

线程类:JIoEndpoint.Work

在JIoEndpoint.Work的run方法中调用await方法等待并获得下一个socket,传给handle进行处理。在await方法中,如果没有分配新的客户端请求socket, available变量会一直false,并会循环调用wait方法阻塞自己,同时释放Work对象的锁,直到Acceptor线程获得新的socket, 并调用Work.assign方法分配给该工作线程。 这时availble变量才为设置为true,并且await方法会返回分配的socket对象。

protected class Worker implements Runnable {
 
    protected Thread thread = null;
 
    protected boolean available = false;
 
    protected Socket socket = null;
 
    /**
10  
11          * Process an incoming TCP/IP connection on the specified socket.  Any
12  
13          * exception that occurs during processing must be logged and swallowed.
14  
15          * <b>NOTE</b> :  This method is called from our Connector's thread.  We
16  
17          * must assign it to our own thread so that multiple simultaneous
18  
19          * requests can be handled.
20  
21          *
22  
23          * @param socket TCP socket to process
24  
25          */
26  
27     synchronized void assign(Socket socket ) {
28  
29         // Wait for the Processor to get the previous Socket
30  
31         while (available ) {
32  
33             try {
34  
35                     wait();
36  
37             } catch (InterruptedException e) {
38  
39             }
40  
41         }
42  
43         // Store the newly available Socket and notify our thread
44  
45         this.socket = socket ;
46  
47         available = true ;
48  
49         notifyAll();
50  
51     }
52  
53     /**
54  
55      * 等待新分配的Socket
56  
57      */
58  
59     private synchronized Socket await() {
60  
61         //等待Connector提供新的Socket
62  
63         while (!available ) {
64  
65             try {
66  
67                     wait();
68  
69             } catch (InterruptedException e) {
70  
71             }
72  
73         }
74  
75         //通知Connector我们已经接收到这个Socket
76  
77         Socket socket = this.socket ;
78  
79         available = false ;
80  
81         notifyAll();
82  
83         return (socket);
84  
85     }
86  
87     /**
88  
89      * 后台线程,监听进入的TCP/IP连接,并传递给合适的处理模块
90  
91      */
92  
93     public void run() {
94  
95         // Process requests until we receive a shutdown signal
96  
97         //处理请求直到我们接收到shutdown信号
98  
99         while (running ) {
100  
101                 //等待下一个分配的socket
102  
103             Socket socket = await();
104  
105             if (socket == null)
106  
107                 continue;
108  
109             //设置socket的选项,并处理socket
110  
111             if (!setSocketOptions(socket) || !handler.process(socket)) {
112  
113                 // 关闭socket
114  
115                 try {
116  
117                     socket.close();
118  
119                 } catch (IOException e) {
120  
121                 }
122  
123             }
124  
125             // Finish up this request
126  
127             socket = null;
128  
129             //回收线程
130  
131             recycleWorkerThread( this);
132  
133         }
134  
135     }
136  
137     /**
138  
139      * 开启后台处理线程
140  
141      */
142  
143     public void start() {
144  
145         thread = new Thread(this);
146  
147         thread.setName(getName() + "-" + (++curThreads));
148  
149         thread.setDaemon(true);
150  
151         thread.start();
152  
153     }
154  
155 }
156  
157  

所属线程池

所属线程池实现功能比较简单,是内嵌到JIoEndpoint类中的实现。基本数据结构是一个工作线程栈JIoEndpoint.WorkerStack。

线程池主要属性

curThreadsBusy:当前繁忙线程数

curThreads:当前工作线程数

maxThreads:最大工作线程数

线程池启动

这个线程池实现功能比较简单,不需要太多启动功能。可以从JIoEndpoint类的start方法看到,启动初始化需要做的事是分配线程栈worker空间。

任务分配时序图

1

任务分配

通过JIoEndPoint中createWorkerThread方法获得一个工作线程。如在工作线程栈workers中获得一个线程对象,如果线程栈已经是空的,并且当前线程数量curThreads还小于最大线程数maxThreads,那么就创建一个新的工作线程。然后调用Work.assign方法分配给工作线程。

protected Worker createWorkerThread() {
 
    //获得工作线程栈workers的锁
 
    synchronized (workers ) {
 
        //如果工作线程栈里有线程则返回栈顶工作线程
 
        if (workers .size() > 0) {
10  
11             curThreadsBusy++;
12  
13             return workers .pop();
14  
15          }
16  
17          //如果工作线程栈里没有线程,maxThreads大于0且当前线程数小于最大线程数,则创建一个新的线程
18  
19         if ((maxThreads > 0) && (curThreads < maxThreads)) {
20  
21             curThreadsBusy++;
22  
23             return (newWorkerThread());
24  
25         } else {
26  
27             //如果maxThreads小于0,则说明没有限制,创建新的线程
28  
29             if (maxThreads < 0) {
30  
31                 curThreadsBusy++;
32  
33                 return (newWorkerThread());
34  
35             } else {
36  
37                 return (null);
38  
39             }
40  
41         }
42  
43     }
44  
45 }
46  
47  

工作线程回收

JIoEndPoint中recycleWorkerThread方法是回收工作线程,当http请求处理完成,则调用该方法回收工作线程。该方法首先获得worker对象锁,然后调用workers.push方法将工作线程压入工作线程栈中,接着将当前繁忙线程数减1,最后调用workers.notify方法。

protected void recycleWorkerThread(Worker workerThread) {
 
    synchronized (workers ) {
 
        workers.push(workerThread);
 
        curThreadsBusy--;
 
        workers.notify();
10  
11     }
12 }

 

配置

在Tomcat中配置文件Server.xml中的Connector属性配置最大线程数maxThreads。

例如:

<Connector port="8080"

maxThreads="150"

……/>

 

Acceptor线程

 

功能

获得HTTP请求socket。并从工作线程池中获得一个线程,将socket分配给一个工作线程。

名称

http-[IPAddr]-[Port]-Acceptor-[Number],如http-0.0.0.0-8080-Acceptor-1

线程类:JIoEndpoint.Acceptor

 

所属线程池

启动时序图

在启动时会开启Accepter线程,时序图如下:

2

线程启动

如上时序图,在Tomcat启动过程会调用JIoEndpoint类的start方法,会创建并启动acceptorThreadCount个Acceptor线程。

public void start() throws Exception {
 
    // Initialize socket if not done before
 
    if (!initialized ) {
 
        init();
 
    }
10  
11     if (!running ) {
12  
13         running = true ;
14  
15         paused = false ;
16  
17         //如果没有配置executor线程池,则创建工作线程栈worker, 就是上例中的线程池的工作线程栈。
18  
19         if (executor == null) {
20  
21             workers = new WorkerStack(maxThreads);
22  
23         }
24  
25         //启动acceptor线程
26  
27         for (int i = 0; i < acceptorThreadCount; i++) {
28  
29              Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
30  
31              acceptorThread.setPriority( threadPriority);
32  
33              acceptorThread.setDaemon( daemon);
34  
35              acceptorThread.start();
36  
37         }
38  
39     }
40  
41 }

属性

acceptorThreadCount:开启的acceptor线程数,从源码看到这个值并没有通过配置设置,而是固定的值为1

配置

 

Main主线程

 

功能

完成装配、初始化和启动,之后会开启SocketServer,并循环等待命令,如shutdown。

名称:Main

 

线程类:Main主线程

 

所属线程池:

 

catalina-exec线程

 

功能

StandardThreadExecutor的工作线程,功能和Work线程类似。如果为Connector配置了Executor,则会使用该线程处理http请求。

线程类:ThreadPoolExecutor.Work

所属线程池:StandardThreadExecutor

类名是org.apache.catalina.core.StandardThreadExecutor,该线程池类通过代理设计模式对Java Concurrent包中的线程池ThreadPoolExecutor进行简单的封装。并实现了Lifecycle接口,以及增加了发送消息的功能。

属性

minSpareThreads:最小空闲线程数

maxThreads:最大线程数

maxIdleTime:最大空闲时间

配置

在Server.xml文件中配置Executor节点,支持如下属性,

Name

Executor的名称

namePrefix

工作线程前缀

maxThreads

最大线程数

minSpareThreads

最小空闲线程数

maxIdleTime

最大空闲时间

并在Connector节点配置executor,并指定为Executor的名称。

例如:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4" maxIdleTime="200"/>

<Connector Address="0.0.0.0" port="8080" protocol="HTTP/1.1"executor="tomcatThreadPool".../>

 

TP-Processor线程

 

功能

AJP协议中Servlet容器的处理线程

名称

TP-Processor-[Number],例如TP-Processor-1

线程类:ThreadPool.ControlRunnable

 

所属线程池:org.apache.tomcat.util.threads.ThreadPool

该线程池还会启动一个TP-Monitor线程监控空闲线程。在TheadPool会有一个ControlRunnable数组保存线程池中的工作线程。使用该线程池需要先调用start方法,进行ControlRunnable数组初始化,minSpareThreads个空闲线程的创建,以及TP-Monitor线程的启动。

属性

maxThreads:最大线程数

minSpareThreads:最小空闲线程数

maxSpareThreads: 最大空闲线程数

线程池的启动

通过ThreadPool.start方法,该方法会分配线程数组pool,并打开minSpareThreads空线程。如果最大空闲线程数小于最大线程数,则启动TP-Monitor线程。

public synchronized void start() {
 
    stopThePool=false ;
 
    currentThreadCount  = 0;
 
    currentThreadsBusy  = 0;
 
    adjustLimits();
10  
11     pool = new ControlRunnable[maxThreads];
12  
13     //启动minSpareThreads空闲线程
14  
15     openThreads( minSpareThreads);
16  
17     //如果最大空闲线程数小于最大线程数,则启动TP-Monitor线程
18  
19     if (maxSpareThreads < maxThreads) {
20  
21         monitor = new MonitorRunnable(this);
22  
23     }
24     
25 }

任务分配

使用ThreadPool.runIt来运行新的任务,在该方法中,会调用findControlRunnable方法来获得一个工作线程。需要注意的是调用方不需要调用额外的方法来回收线程。当ControlRunnable线程完成指定的任务会自动将线程回收到线程池中。

findControlRunnable是ThreadPool线程池的关键方法,它提供了从线程池中获得一个工作线程,并将相应的计数调整,如 tpOpen,currentThreadsBusy。

/**
 
 * Executes a given Runnable on a thread in the pool, block if needed.
 
 */
 
public void runIt(ThreadPoolRunnable r) {
 
    if(null == r) {
10  
11         throw new NullPointerException();
12  
13     }
14  
15     //从线程池中获得一个工作线程
16  
17     ControlRunnable c = findControlRunnable();
18  
19     //运行任务
20  
21     c.runIt(r);
22  
23 }
24  
25 private ControlRunnable findControlRunnable() {
26  
27     ControlRunnable c= null;
28  
29     if ( stopThePool ) {
30  
31         throw new IllegalStateException();
32  
33     }
34  
35     //从线程池中获得一个空闲线程
36  
37     synchronized(this ) {
38  
39         //当前繁忙线程和当前线程数相同,则表示所有的开启线程都是繁忙的。
40  
41         while (currentThreadsBusy == currentThreadCount) {
42  
43             //如果当前线程数比最大线程数小
44  
45             if (currentThreadCount < maxThreads) {
46  
47                 // Not all threads were open,
48  
49                 // Open new threads up to the max number of idel threads
50  
51  
52                 int toOpen = currentThreadCount + minSpareThreads;
53  
54                 openThreads(toOpen);
55  
56             } else {
57  
58                 logFull(log, currentThreadCount, maxThreads );
59  
60                 //线程数已经满了,等待线程成为空闲线程
61  
62                 try {
63  
64                    this.wait();
65  
66                 }
67  
68                 // was just catch Throwable -- but no other
69  
70                 // exceptions can be thrown by wait, right?
71  
72                 // So we catch and ignore this one, since
73  
74                 // it'll never actually happen, since nowhere
75  
76                 // do we say pool.interrupt().
77  
78                 catch(InterruptedException e) {
79  
80                    log.error("Unexpected exception" , e);
81  
82                 }
83  
84                 if( log .isDebugEnabled() ) {
85  
86                    log.debug("Finished waiting: CTC=" +currentThreadCount +
87  
88                    ", CTB=" + currentThreadsBusy );
89  
90                 }
91  
92                 // Pool was stopped. Get away of the pool.
93  
94                 if( stopThePool ) {
95  
96                    break;
97  
98                 }
99  
100             }
101  
102        }
103  
104        //线程池已经关闭,离开线程池
105  
106        if(0 == currentThreadCount || stopThePool) {
107  
108               throw new IllegalStateException();
109  
110         }
111  
112         //到了这里,表示有空闲线程可用
113  
114         //取出数组pool中最后一个线程
115  
116         int pos = currentThreadCount - currentThreadsBusy - 1;
117  
118         c = pool[pos];
119  
120         pool[pos] = null;
121  
122         //繁忙线程数加1
123  
124         currentThreadsBusy++;
125  
126     }
127  
128     return c;
129  
130 }
131  
132 /** 
133  
134  *开启线程
135  
136  * @param toOpen 我们将要开启的线程数
137  
138  */
139  
140 protected void openThreads(int toOpen) {
141  
142     if(toOpen > maxThreads ) {
143  
144          toOpen = maxThreads;
145  
146     }
147  
148     //创建空闲线程
149  
150     for(int i = currentThreadCount ; i < toOpen ; i++) {
151  
152         //需要减去currentThreadsBusy, 因为繁忙线程已经从pool数组中移出
153  
154         pool[i - currentThreadsBusy ] = new ControlRunnable( this);
155  
156     }
157  
158     currentThreadCount = toOpen;
159  
160 }

 

工作线程回收

通过ThreadPool.returnController方法回收线程。该方法会将繁忙线程数currentThreadsBusy减1,并将线程回收到线程数组中。

/**
 
 * 将线程返还线程池
 
 */
protected synchronized void returnController (ControlRunnable c) {
 
    if(0 == currentThreadCount || stopThePool) {
 
10         c.terminate();
11  
12         return;
13  
14     }
15  
16     // atomic
17  
18     currentThreadsBusy--;
19  
20     //将线程回收到pool数组中
21  
22     pool[currentThreadCount - currentThreadsBusy - 1] = c;
23  
24     //notify会唤醒在等待线程资源
25  
26     notify();
27  
28 }
 

配置

在Server.xml文件中配置Connector属性

maxThreads

最大线程数

minSpareThreads

最小空闲线程数

maxSpareThreads

最大空闲线程数

例如:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" maxThreads="800" minSpareThreads="50" maxSpareThreads="500" />

 

TP-Monitor线程

 

功能

监控ThreadPool线程池的空闲线程,回收比最大空闲线程数多出的空闲线程。

线程类:ThreadPool.MonitorRunnable

/**
 
 * 定期清理空闲线程
 
*/
 
public static class MonitorRunnable implements Runnable {
 
    ThreadPool p;
10  
11     Thread     t;
12  
13     int interval =WORK_WAIT_TIMEOUT;
14  
15     boolean shouldTerminate ;
16  
17     MonitorRunnable(ThreadPool p) {
18  
19         this.p =p;
20  
21         this.start();
22  
23     }
24  
25     public void start() {
26  
27         shouldTerminate = false ;
28  
29         t = new Thread(this);
30  
31         t.setDaemon( p.getDaemon() );
32  
33         t.setName( p.getName() + "-Monitor");
34  
35         t.start();
36  
37      }
38  
39     public void setInterval(int i ) {
40  
41         this.interval =i;
42  
43     }
44  
45     public void run() {
46  
47         while(true ) {
48  
49             try {
50  
51                 //Wait一段时间
52  
53                 synchronized(this ) {
54  
55                    this.wait(interval );
56  
57                 }
58  
59                 // Check if should terminate.
60  
61                 // termination happens when the pool is shutting down.
62  
63                 if(shouldTerminate ) {
64  
65                    break;
66  
67                 }
68  
69                 //回收空闲线程
70  
71                 p.checkSpareControllers();
72  
73            } catch(Throwable t) {
74  
75                 ThreadPool. log.error("Unexpected exception" , t);
76  
77            }
78  
79        }
80  
81     }
82  
83     public void stop() {
84  
85         this.terminate();
86  
87     }
88  
89     /** 停止monitor线程
90  
91      */
92  
93     public synchronized void terminate() {
94  
95         shouldTerminate = true ;
96  
97         this.notify();
98  
99     }
100  
101 }

ThreadPool.checkSpareControllers方法,用来被TP-Monitor线程调用回收工作线程。

/**
 
 * 被TP-Monitor线程用来回收线程
 
 */
 
protected synchronized void checkSpareControllers() {
 
    if(stopThePool ) {
10  
11         return;
12  
13     }
14  
15     //如果当前空闲线程数大于最大空闲线程数
16  
17     if((currentThreadCount - currentThreadsBusy) > maxSpareThreads) {
18  
19         //回收比最大空闲线程数多出的空闲线程
20  
21         int toFree = currentThreadCount -
22  
23         currentThreadsBusy -
24  
25         maxSpareThreads;
26  
27         for(int i = 0 ; i < toFree ; i++) {
28  
29             ControlRunnable c = pool[currentThreadCount - currentThreadsBusy - 1];
30  
31             c.terminate();
32  
33             pool[currentThreadCount - currentThreadsBusy - 1] = null;
34  
35             currentThreadCount --;
36  
37         }
38  
39     }
40  
41 }
    

所属线程池

ThreadPool线程池

 

ContainerBackgroundProcessor线程

 

功能

容器后台线程,只有设置backgroundProcessorDelay大于0的容器才会启动ContainerBackgroundProcessor线程。该线程会调用当前容器的backgroundProcess方法,并且递归调用 backgroundProcessorDelay值小于等于0的子容器的方法。

从源码中看到只有StandardEngine设置了这个backgroundProcessorDelay值为10,所以只有StandardEngine容器启动ContainerBackgroundProcessor线程, 而其它StandardHost, StandardContext设置的值都是-1。

/**
 
 * 创建一个新的StandardEngine组件,并绑定默认的基础Valve。
 
 */
 
public StandardEngine() {
 
    super();
10  
11     pipeline.setBasic(new StandardEngineValve());
12  
13     /* Set the jmvRoute using the system property jvmRoute */
14  
15     try {
16  
17         setJvmRoute(System. getProperty("jvmRoute"));
18  
19     } catch(Exception ex) {
20  
21     }
22  
23     // Engine将拥有reloading线程
24  
25     backgroundProcessorDelay = 10;
26  
27 }
 

线程类:ContainerBase.ContainerBackgroundProcessor

 
 
/*  
  
 * ContainerBase的保护线程类,调用当前容器的backgroundProcess方法,并在一个固定延时后,  
  
 * 用它的子容器的backgroundProcess方法  
  
 */  
  
protected class ContainerBackgroundProcessor implements Runnable {  
10     
11     public void run() {  
12     
13         while (!threadDone ) {  
14     
15             try {  
16     
17                 Thread. sleep(backgroundProcessorDelay * 1000L);  
18     
19             } catch (InterruptedException e) {  
20     
21                 ;  
22     
23             }  
24     
25             if (!threadDone ) {  
26     
27                 //获得当前容器,作为父容器  
28     
29                 Container parent = (Container) getMappingObject();  
30     
31                 ClassLoader cl =  
32     
33                 Thread. currentThread().getContextClassLoader();  
34     
35                 if (parent.getLoader() != null) {  
36     
37                     cl = parent.getLoader().getClassLoader();  
38     
39                 }  
40     
41                 //处理父容器和所有的子容器  
42     
43                 processChildren(parent, cl);  
44     
45            }  
46     
47         }  
48     
49     }  
50      
51     //处理父容器和所有的子容器 
52    
53     protected void processChildren(Container container, ClassLoader cl) { 
54    
55         try { 
56    
57             //如果父容器的loader不为null,则将当前线程的上下文类加载器contextClassLoader设置为父容器 
58    
59             //的loader的类加载器 
60    
61             if (container.getLoader() != null) { 
62    
63                 Thread. currentThread().setContextClassLoader 
64    
65                         (container.getLoader().getClassLoader()); 
66    
67              } 
68    
69             //调用父容器的backgroundProcess方法 
70    
71             container.backgroundProcess(); 
72    
73        } catch (Throwable t) { 
74    
75            log.error("Exception invoking periodic operation: " , t); 
76    
77        } finally { 
78    
79            Thread. currentThread().setContextClassLoader(cl); 
80    
81        } 
82    
83        //获得父容器的所有子容器 
84    
85        Container[] children = container.findChildren(); 
86    
87        for (int i = 0; i < children.length; i++) { 
88    
89            //如果子容器的backgroundProcessorDelay小于等于0,则递归处理子容器 
90    
91            if (children[i].getBackgroundProcessorDelay() <= 0) { 
92    
93                processChildren(children[i], cl); 
94    
95            } 
96    
97        } 
98    
99    } 
100       
101 }

所属线程池

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 软件工程师面试资料大整合 1 Java 面霸 1 1. int 和 Integer 有什么区别? 8 2. String 和StringBuffer的区别 8 3. 运行时异常与一般异常有何异同? 8 4. 说出ArrayList,Vector,LinkedList的存储性能和特性 8 5. EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 9 6. Collection 和 Collections的区别。 9 7. &和&&的区别。 9 8. HashMap和Hashtable的区别。 10 9. final, finally, finalize的区别。 10 10. sleep() 和 wait() 有什么区别? 10 11. Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型? 10 12. error和exception有什么区别? 11 13. 同步和异步有何异同,在什么情况下分别使用他们?举例说明。 11 14. 简述synchronized和java.util.concurrent.locks.Lock的异同 ? 11 15. 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 11 16. abstract class和interface有什么区别? 12 17. abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 12 18. 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? 12 19. heap和stack有什么区别。 13 20. forward 和redirect的区别 13 21. EJB与JAVA BEAN的区别? 13 22. Static Nested Class 和 Inner Class的不同。 13 23. JSP动态INCLUDE与静态INCLUDE的区别? 14 24. List, Set, Map区别 14 25. 集合类都有哪些?主要方法? 14 26. 简述逻辑操作(&,|,^)与条件操作(&&,||)的区别。 14 27. XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式? 14 28. JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么? 15 29. Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 15 30. 构造器Constructor是否可被override 15 31. try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后? 16 32. 应用服务器与WEB SERVER的区别? 16 33. BS与CS的联系与区别。 16 34. 启动一个线程是用run()还是start()? 17 35. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 18 36. swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上? 18 37. 一个".java"源文件是否可以包括多个类(不是内部类)?有什么限制? 18 38. 比较truncate和delete 命令 18 39. 解释$ORACLE_HOME 和$ORACLE_BASE的区别? 19 40. session与cookie的区别和联系? 19 41. Statement和PrepareStatement的区别 19 42. JSP的内置对象及方法。 19 43. JSP的常用指令 20 44. 四种会话跟踪技术 20 45. Request对象的主要方法: 21 46. jsp有哪些动作?作用分别是什么? 21 47. 两种跳转方式分别是什么?有什么区别? 22 48. get和post的区别? 22 49. JDK,JRE,JVM的区别? 22 50. Java常见类,方法,接口 23 51. 多线程 23 51.1. 线程的基本概念 23 51.2. Java线程有四种状态 23 51.3. 多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 24 51.4. 线程同步的方法。 24 51.5. java有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 25 52. 数据连接池 25 52.1. 连接池的基本原理: 25 52.2. 连接池的工作机制 25 52.3. 建立连接池 26 52.4. 连接池内连接的使用与释放 26 52.5. 配置连接池 26 52.6. 配置tomcat 6.0.10连接池 26 52.7. Hibernate实现数据库的连接不同方式: 28 52.8. 有几种开源的数据库连接池: 29 53. 描述一下JVM加载class文件的原理机制? 30 54. socket编程 30 54.1. 什么是TCP/IP、UDP? 30 54.2. Socket在哪里呢? 31 54.3. Socket是什么呢? 32 54.4. socket的实现步骤 37 55. Servlet 38 55.1. Servlet工作流程 38 55.2. servlet的生命周期 38 55.3. Servlet执行时一般实现哪几个方法? 38 56. 会话跟踪 39 56.1. Cookie 39 56.2. session 39 56.2.1. Session 生命周期 39 57. EJB的几种类型 39 58. 排序都有哪几种方法?请列举。用JAVA实现一个快速排序。 40 59. 请对以下在J2EE常用的名词进行解释(或简单描述) 40 59.1. web 容器 40 59.2. EJB容器 40 59.3. JNDI 40 59.4. JMS 41 59.5. JTA 41 59.6. JAF 41 59.7. RMI/IIOP 41 60. JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块可以抛出异常吗? 41 61. MVC的各个部分都有那些技术来实现?如何实现? 42 62. java实现多态的机制是什么? 42 63. 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收? 42 63.1. 判断该对象是否是时候可以收集方法 43 63.1.1. 引用计数 43 63.1.2. 对象引用遍历 43 63.2. 几种垃圾回收机制 43 63.2.1. 标记-清除收集器 43 63.2.2. 标记-压缩收集器 43 63.2.3. 复制收集器 44 63.2.4. 增量收集器 44 63.2.5. 分代收集器 44 63.2.6. 并发收集器 44 63.2.7. 并行收集器 44 63.3. Sun HotSpot 1.4.1 JVM堆大小的调整 44 63.4. BEA JRockit JVM的使用 45 63.4.1. Bea JRockit JVM支持4种垃圾收集器: 46 63.5. 如何从JVM获取信息来进行调整 46 63.6. Pdm系统JVM调整 47 63.6.1. 服务器:前提内存1G 单CPU 47 63.6.2. 客户机:通过在JNLP文件设置参数来调整客户端JVM 47 64. 什么时候用assert。 47 65. 什么是java序列化,如何实现java序列化? 48 65.1. java序列化、反序列化 48 65.2. 对象的序列化主要有两种用途: 48 65.3. 对象序列化包括如下步骤: 49 65.4. 对象反序列化的步骤如下: 49 66. 反射机制 49 66.1.1. 传统的类型转换。 49 66.1.2. 通过Class对象来获取对象的类型。 49 66.1.3. 通过关键字instanceof或Class.isInstance()方法 49 67. 说出一些常用的类,包,接口,请各举5个 50 68. XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式? 51 69. jdbc 51 69.1. 简述 51 69.2. JDBC调用数据库的基本步骤 52 69.3. JDBC URL 52 70. MVC设计模式 53 71. Hibernate 54 71.1. Hibernate 介绍 54 71.2. Hibernate 实现原理 55 71.3. Hibernate 优点 56 71.4. Hibernate 的缓存体系 56 71.4.1. 一级缓存: 56 71.4.2. 二级缓存: 56 71.4.3. 缓存管理 56 71.5. Hibernate Java对象的状态 58 71.5.1. 临时状态 (transient) 58 71.5.2. 持久化状态(persisted) 58 71.5.3. 游离状态(detached) 58 71.5.4. hibernate的三种状态之间如何转换 59 71.6. Hibernate并发机制,并发问题的处理。 59 71.6.1. Hibernate并发机制 59 71.6.2. 并发问题解决方案 59 71.7. Hibernate是如何延迟加载? 60 71.8. Hibernate怎样实现类之间的关系?(如:一对多、多对多的关系) 60 71.9. 说下Hibernate的缓存机制 60 71.10. Hibernate的查询方式 60 71.11. 如何优化Hibernate? 61 71.12. Hibernate和spring常出现的几个异常 61 71.13. Hibernate与jdbc的联系 62 71.14. Hibernate与Spring的联系 62 71.15. Hibernate自带的分页机制是什么?如果不使用Hibernate自带的分页,则采用什么方式分页? 62 71.16. hibernate一对多配置文件返回的是什么? 63 71.17. hibernate拒绝连接、服务器崩溃的原因?最少写5个 63 71.18. Hibernate主键介绍 63 71.18.1. Assigned 63 71.18.2. Hilo 63 71.18.3. Increment 64 71.18.4. Identity 64 71.18.5. Sequence 64 71.18.6. Native 64 71.18.7. UUID 64 71.18.8. Foreign GUID 65 71.19. Hibernate源码几个包的作用简要介绍 65 72. struts 66 72.1. struts 简介 66 72.2. STRUTS的应用(如STRUTS架构) 66 72.3. 请写出Struts的工作原理、工作机制 67 72.4. struts的处理流程。 67 72.5. Struts 2框架的大致处理流程如下: 68 72.6. Struts体系结构的组件 69 72.7. struts如何实现国际化 70 72.8. struts2.0的常用标签 71 72.9. action是单实例还是多实例,为什么? 73 72.10. Struts的validate框架是如何验证的? 74 72.11. dispatchAction是用什么技术实现的? 74 72.12. struts2.0的mvc模式?与struts1.0的区别? 74 72.13. struts1.2和struts2.0的区别?如何控制两种框架的单例模式? 74 73. Spring 75 73.1. Spring 简介 75 73.2. 为什么要用Spring? 76 73.3. spring工作机制或工作原理 76 73.4. Spring是什么?根据你的理解详细谈谈你的见解。 76 73.5. 项目如何体现Spring的切面编程,具体说明。 77 73.6. 项目用到的Spring的切面编程最多的地方:声明式事务管理。 77 73.7. spring的事务如何配置 77 73.8. transaction有那几种实现(事务处理)(Spring) 79 73.9. Spring IoC 79 73.10. Spring AOP面向方面编程 82 74. 项目为什么使用SSH 85 75. Spring在SSH的作用 86 76. weblogic 86 76.1. 如何给weblogic指定大小的内存? 86 76.2. 如何设定的weblogic的热启动模式(开发模式)与产品发布模式? 86 76.3. 如何启动时不需输入用户名与密码? 86 76.4. 在weblogic管理制台对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件? 86 76.5. 在weblogic发布ejb需涉及到哪些配置文件 87 76.6. 如何在weblogic进行ssl配置与客户端的认证配置或说说j2ee(标准)进行ssl的配置 87 76.7. 如何查看在weblogic已经发布的EJB? 87 76.8. 说说在weblogic开发消息Bean时的persistent与non-persisten的差别 87 77. tomcat 87 77.1. 解决端口冲突导致tomcat无法启动的问题 87 77.2. 修改java虚拟机内存 88 77.3. 修改tomcat连接数 88 77.4. 禁止列出目录下的文件 88 77.5. 设置session失效的时间 89 77.6. 设置MIME响应类型 89 77.7. 设置tomcat的默认访问页面 89 77.8. 设置tomcat管理用户 89 77.9. 附录 90 78. websphere 90 79. 常见异常 90 79.1. nullpointerexception 90 79.2. classnotfoundexception 90 79.3. arithmeticexception 90 79.4. arrayindexoutofboundsexception 91 79.5. illegalargumentexception 91 79.6. illegalaccessexception 91 80. 异常机制 97 81. 异常的分类 97 82. 异常的使用方法 98 83. JAVA代码查错 101 83.1. 判断 101 83.2. 判断 102 83.3. 判断 102 83.4. 判断 102 83.5. 判断 102 83.6. 判断 103 83.7. 判断 103 83.8. 判断 103 83.9. 判断 104 83.10. 判断 104 83.11. 判断 105 84. 编码 106 84.1. 写出一个单例模式 106 84.2. 我们在web应用开发过程经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串? 106 84.3. 设计4个线程,其两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。 107 84.4. 现在输入n个数字,以逗号”,”分开;然后可选择升或者降序排序;按提交键就在另一页面显示按什么排序,结果为,提供reset 108 84.5. 金额转换,阿拉伯数字的金额转换成国传统的形式如:(¥1011)->(一千零一拾一元整)输出。 109 84.6. 内部类的实现方式? 112 84.7. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,6,应该输出为“我ABC”而不是“我ABC+汉的半个”。 113 84.8. 将一个键盘输入的数字转化成文输出(例如:输入1234567,输出:一百二拾三万四千五百六拾七),请用java语言编一段程序实现! 114 84.9. 题目1:用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连. 117 84.10. 写一个方法,实现字符串的反转,如:输入abc,输出cba 119 84.11. 请用java写二叉树算法,实现添加数据形成二叉树功能,并以先序的方式打印出来. 119 84.12. 请写一个java程序实现线程连接池功能? 122 84.13. 编一段代码,实现在控制台输入一组数字后,排序后在控制台输出; 122 84.14. 列出某文件夹下的所有文件; 123 84.15. java调用系统命令实现删除文件的操作; 123 84.16. java实现从文件一次读出一个字符的操作; 124 84.17. 列出一些控制流程的方法; 124 84.18. 编写了一个服务器端的程序实现在客户端输入字符然后在控制台上显示,直到输入"END"为止,让你写出客户端的程序; 124 84.19. 用jdom解析xml文件时如何解决文问题?如何解析? 127 84.20. Jquery ajax 实现异步 129

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值