tomcat每次请求都是new线程吗(tomcat每次改动都要重启)

互联网- 2023-08-04 08:01:29

tomcat线程无法回收

style="text-indent:2em;">今天给各位分享tomcat每次请求都是new线程吗的知识,其中也会对不建议直接new线程进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录

  1. C#怎么启动新的线程
  2. 线程异常,如何检测,解决
  3. tomcat每次请求都是new线程吗
  4. 多线程返回值问题

C#怎么启动新的线程

privatevoidThreadFun()

{

//线程操作

}

//需要启动线程的方法

privatevoidFun1()

{

Threadm_thread=newThread(ThreadFun);

m_thread.Start();

}

还需要加一个usingSystem.Threading;

线程异常,如何检测,解决

线程出现异常测试

任务类:Task.javapublicclassTaskimplementsRunnable{

privateinti;

publicTask(inti){

this.i=i;

}

@Override

publicvoidrun(){

if(i==5){

//System.out.println("throwexception");

thrownewIllegalArgumentException();

}

System.out.println(i);

}

}

如果i==5,将抛出一个异常

线程测试类:TaskTest.java

publicclassTestTask{

publicstaticvoidmain(String[]args){

inti=0;

while(true){

if(i==10)break;

try{

newThread(newTask(i++)).start();

}catch(Exceptione){

System.out.println("catchexception...");

}

}

}

}

通过使用try-catch,尝试对抛出的异常进行捕获

测试结果

ConnectedtothetargetVM,address:'127.0.0.1:64551',transport:'socket'

0

1

2

3

4

6

7

8

9

Exceptioninthread"pool-1-thread-1"java.lang.IllegalArgumentException

atcom.h2t.study.thread.Task.run(Task.java:21)

atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

atjava.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

atjava.lang.Thread.run(Thread.java:748)

异常没有被捕获,只是在控制台打印了异常,并且不影响后续任务的执行emmmm这是为什么呢,捕获不到异常就不知道程序出错了,到时候哪天有个任务不正常排查都排查不到,这样是要不得的。看一下Thread这个类,有个叫dispatchUncaughtException的方法,作用如其名,分发未捕获的异常,把这段代码揪出来:Thread#dispatchUncaughtException

privatevoiddispatchUncaughtException(Throwablee){

getUncaughtExceptionHandler().uncaughtException(this,e);

}

findusage是找不到该方法在哪里调用的,因为这个方法只被JVM调用Thread#getUncaughtExceptionHandler:获取UncaughtExceptionHandler接口实现类

publicUncaughtExceptionHandlergetUncaughtExceptionHandler(){

returnuncaughtExceptionHandler!=null?

uncaughtExceptionHandler:group;

}

UncaughtExceptionHandler是Thread中定义的接口,在Thread类中uncaughtExceptionHandler默认是null,因此该方法将返回group,即实现了UncaughtExceptionHandler接口的ThreadGroup类UncaughtExceptionHandler#uncaughtException:ThreadGroup类的uncaughtException方法实现

publicvoiduncaughtException(Threadt,Throwablee){

if(parent!=null){

parent.uncaughtException(t,e);

}else{

Thread.UncaughtExceptionHandlerueh=

Thread.getDefaultUncaughtExceptionHandler();

if(ueh!=null){

ueh.uncaughtException(t,e);

}elseif(!(einstanceofThreadDeath)){

System.err.print("Exceptioninthread\""

+t.getName()+"\"");

e.printStackTrace(System.err);

}

}

}

因为在Thread类中没有对group【parent】和defaultUncaughtExceptionHandler【Thread.getDefaultUncaughtExceptionHandler】进行赋值,因此将进入最后一层条件,将异常打印到控制台中,对异常不做任何处理。整个异常处理器调用链如下:

首先判断默认异常处理器【defaultUncaughtExceptionHandler】是不是为null,在判断线程组异常处理器【group】是不是为null,在判断自定义异常处理器【uncaughtExceptionHandler】是不是为null,都为null则在控制台打印异常

线程异常处理

分析了一下源码就知道如果想对任务执行过程中的异常进行处理一个就是让ThreadGroup不为null,另外一种思路就是让UncaughtExceptionHandler类型的变量值不为null。

异常处理器:ExceptionHandler.java

privatestaticclassExceptionHandlerimplementsThread.UncaughtExceptionHandler{

@Override

publicvoiduncaughtException(Threadt,Throwablee){

System.out.println("异常捕获到了:"+e);

}

}

设置默认异常处理器

Thread.setDefaultUncaughtExceptionHandler((t,e)->System.out.println("异常捕获到了:"+e));

inti=0;

while(true){

if(i==10)break;

Threadthread=newThread(newTask(i++));

thread.start();

}

打印结果:

0

2

1

3

9

6

7

4

异常捕获到了:java.lang.IllegalArgumentException

8

通过设置默认异常就不需要为每个线程都设置一次了

设置自定义异常处理器

Threadt=newThread(newTask(i++));

t.setUncaughtExceptionHandler(newExceptionHandler());

打印结果:

0

2

4

异常捕获到了:java.lang.IllegalArgumentException

6

1

3

7

9

8

设置线程组异常处理器

MyThreadGroupmyThreadGroup=newMyThreadGroup("测试线程线程组");

Threadt=newThread(myThreadGroup,newTask(i++))

自定义线程组:MyThreadGroup.java

privatestaticclassMyThreadGroupextendsThreadGroup{

publicMyThreadGroup(Stringname){

super(name);

}

@Override

publicvoiduncaughtException(Threadt,Throwablee){

System.out.println("捕获到异常了:"+e);

}

}

打印结果:

1

2

0

4

3

6

7

8

9

捕获到异常了:java.lang.IllegalArgumentException

线程组异常捕获处理器很适合为线程进行分组处理的场景,每个分组出现异常的处理方式不相同设置完异常处理器后异常都能被捕获了,但是不知道为什么设置异常处理器后任务的执行顺序乱了,难道是因为为每个线程设置异常处理器的时间不同【想不通】

线程池异常处理

一般应用中线程都是通过线程池创建复用的,因此对线程池的异常处理就是为线程池工厂类【ThreadFactory实现类】生成的线程添加异常处理器

默认异常处理器

Thread.setDefaultUncaughtExceptionHandler(newExceptionHandler());

ExecutorServicees=Executors.newCachedThreadPool();

es.execute(newTask(i++))

自定义异常处理器

ThreadPoolExecutorthreadPoolExecutor=newThreadPoolExecutor(1,1,

0L,TimeUnit.MILLISECONDS,

newLinkedBlockingQueue<Runnable>());

threadPoolExecutor.setThreadFactory(newMyThreadFactory());

threadPoolExecutor.execute(newTask(i++));

自定义工厂类:

MyThreadFactory.java

privatestaticclassMyThreadFactoryimplementsThreadFactory{

@Override

publicThreadnewThread(Runnabler){

Threadt=newThread();

//自定义UncaughtExceptionHandler

t.setUncaughtExceptionHandler(newExceptionHandler());

returnt;

}

}

设计原则,为什么要由线程自身进行捕获

来自JVM的设计理念"线程是独立执行的代码片断,线程的问题应该由线程自己来解决,而不要委托到外部"。因此在Java中,线程方法的异常【即任务抛出的异常】,应该在线程代码边界之内处理掉,而不应该在线程方法外面由其他线程处理

线程执行Callable任务

前面介绍的是线程执行Runnable类型任务的情况,众所周知,还有一种有返回值的Callable任务类型测试代码:

TestTask.java

publicclassTestTask{

publicstaticvoidmain(String[]args){

inti=0;

while(true){

if(i==10)break;

FutureTask<Integer>task=newFutureTask<>(newCallableTask(i++));

Threadthread=newThread(task);

thread.setUncaughtExceptionHandler(newExceptionHandler());

thread.start();

}

}

privatestaticclassExceptionHandlerimplementsThread.UncaughtExceptionHandler{

@Override

publicvoiduncaughtException(Threadt,Throwablee){

System.out.println("异常捕获到了:"+e);

}

}

}

打印结果:

DisconnectedfromthetargetVM,address:'127.0.0.1:64936',transport:'socket'

0

1

2

3

4

6

7

8

9

观察结果,异常没有被捕获,thread.setUncaughtExceptionHandler(newExceptionHandler())方法设置无效,emmmmm,这又是为什么呢,在问为什么就是十万个为什么儿童了。查看FutureTask的run方法,FutureTask#run:

publicvoidrun(){

if(state!=NEW||

!UNSAFE.compareAndSwapObject(this,runnerOffset,

null,Thread.currentThread()))

return;

try{

Callable<V>c=callable;

if(c!=null&&state==NEW){

Vresult;

booleanran;

try{

result=c.call();

ran=true;

}catch(Throwableex){

result=null;

ran=false;

setException(ex);

}

if(ran)

set(result);

}

}finally{

//runnermustbenon-nulluntilstateissettledto

//preventconcurrentcallstorun()

runner=null;

//statemustbere-readafternullingrunnertoprevent

//leakedinterrupts

ints=state;

if(s>=INTERRUPTING)

handlePossibleCancellationInterrupt(s);

}

}

FutureTask#setException:

protectedvoidsetException(Throwablet){

if(UNSAFE.compareAndSwapInt(this,stateOffset,NEW,COMPLETING)){

//将异常设置给outcome变量

outcome=t;

//设置任务的状态为EXCEPTIONAL

UNSAFE.putOrderedInt(this,stateOffset,EXCEPTIONAL);//finalstate

finishCompletion();

}

}

看到catch这段代码,当执行任务捕获到异常的时候,会将任务的处理结果设置为null,并且调用setException方法对捕获的异常进行处理,因为setUncaughtExceptionHandler只对未捕获的异常进行处理,FutureTask已经对异常进行了捕获处理,因此调用setUncaughtExceptionHandler捕获异常无效对任务的执行结果调用get方法:

inti=0;

while(true){

if(i==10)break;

FutureTask<Integer>task=newFutureTask<>(newCallableTask(i++));

Threadthread=newThread(task);

thread.setUncaughtExceptionHandler(newExceptionHandler());

thread.start();

//打印结果

try{

System.out.println(task.get());

}catch(Exceptione){

System.out.println("异常被抓住了,e:"+e);

}

}

执行结果将会将捕获到的异常打印出来,执行结果:

0

1

2

3

4

异常被抓住了,e:java.util.concurrent.ExecutionException:java.lang.IllegalArgumentException

6

7

DisconnectedfromthetargetVM,address:'127.0.0.1:50900',transport:'socket'

8

9

FutureTask#get:

publicVget()throwsInterruptedException,ExecutionException{

ints=state;

if(s<=COMPLETING)

//未完成等待任务执行完成

s=awaitDone(false,0L);

returnreport(s);

}

FutureTask#report:

privateVreport(ints)throwsExecutionException{

Objectx=outcome;

if(s==NORMAL)

return(V)x;

if(s>=CANCELLED)

thrownewCancellationException();

thrownewExecutionException((Throwable)x);

}

outcome在setException方法中被设置为了异常,并且s为state的状态最终8被设置为EXCEPTIONAL,因此方法将捕获的任务抛出【newExecutionException((Throwable)x)】

总结:

Callable任务抛出的异常能在代码中通过try-catch捕获到,但是只有调用get方法后才能捕获到

【北京】IT技术人员面对面试、跳槽、升职等问题,如何快速成长,获得大厂入门资格和升职加薪的筹码?与大厂技术大牛面对面交流,解答你的疑惑。《从职场小白到技术总监成长之路:我的职场焦虑与救赎》活动链接:http://mk1.top/1ndjnvb

想了解更多Java相关,百度搜索圈T社区www.aiquanti.com,免费视频教程。纯干货

tomcat每次请求都是new线程吗

1.tomcat每次请求不一定都是new线程。

对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。如果同时进来的请求多于当前可用的请求处理线程数,额外的线程就会被创建,直到到达配置的最大线程数(maxThreads属性值)。如果仍就同时接收到更多请求,这些来不及处理的请求就会在Connector创建的ServerSocket中堆积起来,直到到达最大的配置值(acceptCount属性值)。至此,任何再来的请求将会收到

connectionrefused错误,直到有可用的资源来处理它们。

多线程返回值问题

importjava.util.concurrent.Callable;

/**

*线程类,需要返回值的,实现Callable接口

*@authorxhc

*

*/

@SuppressWarnings("rawtypes")

publicclassMyThreadimplementsCallable{

@SuppressWarnings("static-access")

@Override

publicObjectcall()throwsException{

Thread.currentThread().sleep(1000);//睡眠一秒

returnThread.currentThread().getName();

}

}

测试类:

packagecom.xjiuge.test;

importjava.util.ArrayList;

importjava.util.List;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

importjava.util.concurrent.Future;

publicclassApp{

//建立线程池

staticExecutorServicepool=Executors.newCachedThreadPool();

@SuppressWarnings("unchecked")

publicstaticvoidmain(String[]args){

//存放future的集合

List<Future<String>>list=newArrayList<>();

longst=System.currentTimeMillis();//开始时间

//循环5次,开启5个线程

for(inti=0;i<5;i++){

//获取线程类返回的值,用future接收

Future<String>future=pool.submit(newMyThread());

//将future放入list

list.add(future);

}

try{

//遍历list读取future中的值

for(Future<String>future:list){

while(true){

//判断线程操作是否执行完毕,并且操作没有被取消掉

if(future.isDone()&&!future.isCancelled()){

//调用get方法获取返回值

Stringresult=future.get().toString();

System.out.println(result);

break;

}

}

}

}catch(Exceptione){

e.printStackTrace();

}

longet=System.currentTimeMillis();//结束时间

System.out.println("总耗时:"+(et-st)+"ms");

}

}

打印结果:

pool-1-thread-1

pool-1-thread-2

pool-1-thread-3

pool-1-thread-4

pool-1-thread-5

总耗时:1004ms

OK,本文到此结束,希望对大家有所帮助。

详解 Tomcat 的连接数与线程池 javafirst CSDN博客 tomcat 下载连接数量
  • 声明:本文内容来自互联网不代表本站观点,转载请注明出处:bk.66688815.com/1/83617.html
上一篇:switch一直提示nosd关不了(switch一直弹出l+r)
下一篇:steam账号交易有风险吗(steam游戏账号交易)
相关文章
返回顶部小火箭