网站维护一般怎么做,优对 网站开发,多少钱英文,东莞公共资源交易中心官网1. 问题背景
有一天给同事CR#xff0c;看到一段这样的代码
try {for (param : params) {//并发处理#xff0c;func无返回值ThreadPool.submit(func(param));}
} catch (Exception e) {log.info(func抛异常啦,参数是:{}, param)
}
我#xff1a;你这段代码是…1. 问题背景
有一天给同事CR看到一段这样的代码
try {for (param : params) {//并发处理func无返回值ThreadPool.submit(func(param));}
} catch (Exception e) {log.info(func抛异常啦,参数是:{}, param)
}
我你这段代码是利用并发降低RT对吧如果func内部抛异常你确定可以catch到吗
同事可以啊 为什么不可以...
我不如你run一把在func mock一个异常出来试试
同事我靠还真是
我你可以用execute改动比较小
同事那么是为什么呢
2. 同事的例子
import java.util.concurrent.*;public class ThreadPoolTest {public static void main(String[] args) throws Exception {ExecutorService executorService new ThreadPoolExecutor(10, 20, 10, TimeUnit.SECONDS, new LinkedBlockingQueue());testExecute(executorService);Thread.sleep(2000);testSubmit1(executorService);Thread.sleep(2000);testSubmit2(executorService);}private static void testExecute(ExecutorService executorService) {executorService.execute(() - {System.out.println(执行线程池execute方法);throw new RuntimeException(execute方法抛出异常);});}private static void testSubmit1(ExecutorService executorService) {executorService.submit(() - {System.out.println(执行线程池submit方法1);throw new RuntimeException(submit方法1抛出异常);});}private static void testSubmit2(ExecutorService executorService) throws Exception {FutureObject feature executorService.submit(() - {System.out.println(执行线程池submit方法2);throw new RuntimeException(submit方法2抛出异常);});feature.get();}
}执行结果
执行线程池execute方法
Exception in thread pool-1-thread-1 java.lang.RuntimeException: execute方法抛出异常at ThreadPoolTest.lambda$testExecute$0(ThreadPoolTest.java:23)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
执行线程池submit方法1
执行线程池submit方法2
Exception in thread main java.util.concurrent.ExecutionException: java.lang.RuntimeException: submit方法2抛出异常at java.util.concurrent.FutureTask.report(FutureTask.java:122)at java.util.concurrent.FutureTask.get(FutureTask.java:192)at ThreadPoolTest.testSubmit2(ThreadPoolTest.java:39)at ThreadPoolTest.main(ThreadPoolTest.java:17)
Caused by: java.lang.RuntimeException: submit方法2抛出异常at ThreadPoolTest.lambda$testSubmit2$2(ThreadPoolTest.java:37)at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)at java.util.concurrent.FutureTask.run(FutureTask.java)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)3. 原理分析
3.1 线程池包的继承结构 3.2 submit和execute方法的差异
3.2.1 execute
方法定义在最顶层的Executor接口并且Executor接口有且仅有这一个方法
public interface Executor {/*** Executes the given command at some time in the future. The command* may execute in a new thread, in a pooled thread, or in the calling* thread, at the discretion of the {code Executor} implementation.** param command the runnable task* throws RejectedExecutionException if this task cannot be* accepted for execution* throws NullPointerException if command is null*/void execute(Runnable command);
}
方法实现在ThreadPoolExecutor public void execute(Runnable command) {if (command null)throw new NullPointerException();int c ctl.get();if (workerCountOf(c) corePoolSize) {if (addWorker(command, true))return;c ctl.get();}if (isRunning(c) workQueue.offer(command)) {int recheck ctl.get();if (! isRunning(recheck) remove(command))reject(command);else if (workerCountOf(recheck) 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);}
实际执行的过程在worker是runnable的实现类的run方法run方法实际执行的是runWorker方法 final void runWorker(Worker w) {Thread wt Thread.currentThread();Runnable task w.firstTask;w.firstTask null;w.unlock(); // allow interruptsboolean completedAbruptly true;try {while (task ! null || (task getTask()) ! null) {w.lock();// If pool is stopping, ensure thread is interrupted;// if not, ensure thread is not interrupted. This// requires a recheck in second case to deal with// shutdownNow race while clearing interruptif ((runStateAtLeast(ctl.get(), STOP) ||(Thread.interrupted() runStateAtLeast(ctl.get(), STOP))) !wt.isInterrupted())wt.interrupt();try {beforeExecute(wt, task);Throwable thrown null;try {task.run();} catch (RuntimeException x) {thrown x; throw x;} catch (Error x) {thrown x; throw x;} catch (Throwable x) {thrown x; throw new Error(x);} finally {afterExecute(task, thrown);}} finally {task null;w.completedTasks;w.unlock();}}completedAbruptly false;} finally {processWorkerExit(w, completedAbruptly);}}
可以看到执行过程中如果task.run();发生异常没有catch处理异常会层层向外抛出最终进入finally块执行processWorkerExit 3.2.2 submit
submit方法定义在ExecutorService
public interface ExecutorService extends Executor {/*** Submits a value-returning task for execution and returns a* Future representing the pending results of the task. The* Futures {code get} method will return the tasks result upon* successful completion.** p* If you would like to immediately block waiting* for a task, you can use constructions of the form* {code result exec.submit(aCallable).get();}** pNote: The {link Executors} class includes a set of methods* that can convert some other common closure-like objects,* for example, {link java.security.PrivilegedAction} to* {link Callable} form so they can be submitted.** param task the task to submit* param T the type of the tasks result* return a Future representing pending completion of the task* throws RejectedExecutionException if the task cannot be* scheduled for execution* throws NullPointerException if the task is null*/T FutureT submit(CallableT task);/*** Submits a Runnable task for execution and returns a Future* representing that task. The Futures {code get} method will* return the given result upon successful completion.** param task the task to submit* param result the result to return* param T the type of the result* return a Future representing pending completion of the task* throws RejectedExecutionException if the task cannot be* scheduled for execution* throws NullPointerException if the task is null*/T FutureT submit(Runnable task, T result);/*** Submits a Runnable task for execution and returns a Future* representing that task. The Futures {code get} method will* return {code null} upon emsuccessful/em completion.** param task the task to submit* return a Future representing pending completion of the task* throws RejectedExecutionException if the task cannot be* scheduled for execution* throws NullPointerException if the task is null*/Future? submit(Runnable task);
}实现在AbstractExecutorService public Future? submit(Runnable task) {if (task null) throw new NullPointerException();RunnableFutureVoid ftask newTaskFor(task, null);execute(ftask);return ftask;}
可以看到这里创建了RunnableFuture而不是基础的worker顾名思义RunnableFuture同时实现了Runnable和Future接口也就意味着可以对该任务执行get操作看看RunnableFuture的run方法 public void run() {if (state ! NEW ||!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))return;try {CallableV c callable;if (c ! null state NEW) {V result;boolean ran;try {result c.call();ran true;} catch (Throwable ex) {result null;ran false;setException(ex);}if (ran)set(result);}} finally {// runner must be non-null until state is settled to// prevent concurrent calls to run()runner null;// state must be re-read after nulling runner to prevent// leaked interruptsint s state;if (s INTERRUPTING)handlePossibleCancellationInterrupt(s);}}
catch块对方法异常做了处理与执行结果一同在Future中暂存起来submit()执行完毕后返回Future对象执行future.get()会触发异常的抛出
当然了如果你只是执行了submit没有获取future异常就会“神奇地”消失。 参考
Java线程池实现原理及其在美团业务中的实践 - 美团技术团队
https://zhuanlan.zhihu.com/p/651997713 文章转载自: http://www.morning.wgkz.cn.gov.cn.wgkz.cn http://www.morning.nhlnh.cn.gov.cn.nhlnh.cn http://www.morning.ghjln.cn.gov.cn.ghjln.cn http://www.morning.pqndg.cn.gov.cn.pqndg.cn http://www.morning.rdxnt.cn.gov.cn.rdxnt.cn http://www.morning.gjxr.cn.gov.cn.gjxr.cn http://www.morning.dgsr.cn.gov.cn.dgsr.cn http://www.morning.chmkt.cn.gov.cn.chmkt.cn http://www.morning.qdzqf.cn.gov.cn.qdzqf.cn http://www.morning.mmxnb.cn.gov.cn.mmxnb.cn http://www.morning.xllrf.cn.gov.cn.xllrf.cn http://www.morning.dzgyr.cn.gov.cn.dzgyr.cn http://www.morning.saastob.com.gov.cn.saastob.com http://www.morning.qfkdt.cn.gov.cn.qfkdt.cn http://www.morning.yhgbd.cn.gov.cn.yhgbd.cn http://www.morning.swwpl.cn.gov.cn.swwpl.cn http://www.morning.rzysq.cn.gov.cn.rzysq.cn http://www.morning.ybgt.cn.gov.cn.ybgt.cn http://www.morning.nrchx.cn.gov.cn.nrchx.cn http://www.morning.lqjpb.cn.gov.cn.lqjpb.cn http://www.morning.wwdlg.cn.gov.cn.wwdlg.cn http://www.morning.zfhzx.cn.gov.cn.zfhzx.cn http://www.morning.ggnkt.cn.gov.cn.ggnkt.cn http://www.morning.rxydr.cn.gov.cn.rxydr.cn http://www.morning.080203.cn.gov.cn.080203.cn http://www.morning.bfgpn.cn.gov.cn.bfgpn.cn http://www.morning.llfwg.cn.gov.cn.llfwg.cn http://www.morning.rjxwq.cn.gov.cn.rjxwq.cn http://www.morning.trhrk.cn.gov.cn.trhrk.cn http://www.morning.fksrg.cn.gov.cn.fksrg.cn http://www.morning.phzrq.cn.gov.cn.phzrq.cn http://www.morning.lgtcg.cn.gov.cn.lgtcg.cn http://www.morning.bswxt.cn.gov.cn.bswxt.cn http://www.morning.jrkzk.cn.gov.cn.jrkzk.cn http://www.morning.nxhjg.cn.gov.cn.nxhjg.cn http://www.morning.rlbc.cn.gov.cn.rlbc.cn http://www.morning.qzqjz.cn.gov.cn.qzqjz.cn http://www.morning.dsgdt.cn.gov.cn.dsgdt.cn http://www.morning.hphrz.cn.gov.cn.hphrz.cn http://www.morning.xzgbj.cn.gov.cn.xzgbj.cn http://www.morning.wqrk.cn.gov.cn.wqrk.cn http://www.morning.wjxyg.cn.gov.cn.wjxyg.cn http://www.morning.tnmmp.cn.gov.cn.tnmmp.cn http://www.morning.wjlnz.cn.gov.cn.wjlnz.cn http://www.morning.nsrtvu.com.gov.cn.nsrtvu.com http://www.morning.ksjnl.cn.gov.cn.ksjnl.cn http://www.morning.jnoegg.com.gov.cn.jnoegg.com http://www.morning.rmfh.cn.gov.cn.rmfh.cn http://www.morning.kpcxj.cn.gov.cn.kpcxj.cn http://www.morning.jghqc.cn.gov.cn.jghqc.cn http://www.morning.ykshx.cn.gov.cn.ykshx.cn http://www.morning.mbprq.cn.gov.cn.mbprq.cn http://www.morning.sxcwc.cn.gov.cn.sxcwc.cn http://www.morning.fplqh.cn.gov.cn.fplqh.cn http://www.morning.ftwlay.cn.gov.cn.ftwlay.cn http://www.morning.nyzmm.cn.gov.cn.nyzmm.cn http://www.morning.wcjk.cn.gov.cn.wcjk.cn http://www.morning.kdhrf.cn.gov.cn.kdhrf.cn http://www.morning.rnrwq.cn.gov.cn.rnrwq.cn http://www.morning.ndtmz.cn.gov.cn.ndtmz.cn http://www.morning.kgrwh.cn.gov.cn.kgrwh.cn http://www.morning.sphft.cn.gov.cn.sphft.cn http://www.morning.kcnjz.cn.gov.cn.kcnjz.cn http://www.morning.bdzps.cn.gov.cn.bdzps.cn http://www.morning.wtcbl.cn.gov.cn.wtcbl.cn http://www.morning.jfbbq.cn.gov.cn.jfbbq.cn http://www.morning.hrnrx.cn.gov.cn.hrnrx.cn http://www.morning.qkbwd.cn.gov.cn.qkbwd.cn http://www.morning.fplqh.cn.gov.cn.fplqh.cn http://www.morning.xqgtd.cn.gov.cn.xqgtd.cn http://www.morning.pnntx.cn.gov.cn.pnntx.cn http://www.morning.txlnd.cn.gov.cn.txlnd.cn http://www.morning.wwklf.cn.gov.cn.wwklf.cn http://www.morning.gydth.cn.gov.cn.gydth.cn http://www.morning.qbjrf.cn.gov.cn.qbjrf.cn http://www.morning.gfnsh.cn.gov.cn.gfnsh.cn http://www.morning.nqyfm.cn.gov.cn.nqyfm.cn http://www.morning.zmpsl.cn.gov.cn.zmpsl.cn http://www.morning.kqpq.cn.gov.cn.kqpq.cn http://www.morning.mwmtk.cn.gov.cn.mwmtk.cn