关于 java.util.concurrent 您不知道的 5 件事
- 格式:pdf
- 大小:184.61 KB
- 文档页数:15
java juc详解Java JUC(Java Util Concurrent)是Java编程语言的一个扩展库,用于实现多线程并发编程。
JUC库提供了一系列的工具类和接口,用于解决多线程编程中的一些常见问题,如线程安全、并发控制、线程间通信等。
在多线程编程中,线程的安全性是一个重要的问题。
线程安全性指的是多个线程同时访问一个共享资源时,不会引发任何问题。
JUC 提供了一些线程安全的数据结构,如ConcurrentHashMap、ConcurrentLinkedQueue等。
这些数据结构在内部使用了锁和CAS(Compare and Swap)等机制来保证线程安全性。
除了线程安全性,JUC还提供了一些并发控制的机制。
例如,Semaphore可以用来控制同时访问某个资源的线程数量;CountDownLatch可以用来实现线程的等待,直到某个条件满足后才继续执行;CyclicBarrier可以用来实现线程的同步,多个线程在达到某个屏障点之前都会被阻塞等待。
线程间的通信也是多线程编程中的一个重要问题。
JUC提供了一些用于线程间通信的机制,如BlockingQueue和Exchanger。
BlockingQueue是一个阻塞队列,多个线程可以通过它来进行数据的交换。
Exchanger则是一个用于两个线程之间交换数据的工具类。
除了上述的工具类和接口,JUC还提供了一些常用的并发执行框架。
例如,Executor框架可以用来管理和调度多个线程的执行;Fork/Join框架可以用来实现任务的拆分和合并,以实现并行计算;并发集合类则可以用来管理和操作一组共享的数据。
JUC库的设计目标是提供高效、可扩展和易用的多线程编程工具。
在实现上,JUC库使用了一些高级的并发控制技术,如锁、条件变量、信号量等。
这些技术可以有效地提高多线程程序的性能和可靠性。
总结来说,Java JUC是Java编程语言的一个扩展库,用于实现多线程并发编程。
java.util.ConcurrentModificationException异常问题详解环境:JDK 1.8.0_111在Java开发过程中,使⽤iterator遍历集合的同时对集合进⾏修改就会出现java.util.ConcurrentModificationException异常,本⽂就以ArrayList为例去理解和解决这种异常。
⼀、单线程情况下问题分析及解决⽅案1.1 问题复现先上⼀段抛异常的代码。
1public void test1() {2 ArrayList<Integer> arrayList = new ArrayList<>();3for (int i = 0; i < 20; i++) {4 arrayList.add(Integer.valueOf(i));5 }67// 复现⽅法⼀8 Iterator<Integer> iterator = arrayList.iterator();9while (iterator.hasNext()) {10 Integer integer = iterator.next();11if (integer.intValue() == 5) {12 arrayList.remove(integer);13 }14 }1516// 复现⽅法⼆17 iterator = arrayList.iterator();18for (Integer value : arrayList) {19 Integer integer = iterator.next();20if (integer.intValue() == 5) {21 arrayList.remove(integer);22 }23 }24 }在这个代码中展⽰了两种能抛异常的实现⽅式。
1.2、问题原因分析先来看实现⽅法⼀,⽅法⼀中使⽤Iterator遍历ArrayList,抛出异常的是iterator.next()。
Java并发编程之java.util.concurrent包下常见类的使⽤⼀,Condition⼀个场景,两个线程数数,同时启动两个线程,线程A数1、2、3,然后线程B数4、5、6,最后线程A数7、8、9,程序结束,这涉及到线程之间的通信。
public class ConditionTest {static class NumberWrapper {public int value = 1;}public static void main(String[] args) {//初始化可重⼊锁final Lock lock = new ReentrantLock();//第⼀个条件当屏幕上输出到3final Condition reachThreeCondition = lock.newCondition();//第⼆个条件当屏幕上输出到6final Condition reachSixCondition = lock.newCondition();//NumberWrapper只是为了封装⼀个数字,⼀边可以将数字对象共享,并可以设置为final//注意这⾥不要⽤Integer, Integer 是不可变对象final NumberWrapper num = new NumberWrapper();//初始化A线程Thread threadA = new Thread(new Runnable() {@Overridepublic void run() {//需要先获得锁lock.lock();System.out.println("ThreadA获得lock");try {System.out.println("threadA start write");//A线程先输出前3个数while (num.value <= 3) {System.out.println(num.value);num.value++;}//输出到3时要signal,告诉B线程可以开始了reachThreeCondition.signal();} finally {lock.unlock();System.out.println("ThreadA释放lock");}lock.lock();try {//等待输出6的条件System.out.println("ThreadA获得lock");reachSixCondition.await();System.out.println("threadA start write");//输出剩余数字while (num.value <= 9) {System.out.println(num.value);num.value++;}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();System.out.println("ThreadA释放lock");}}});Thread threadB = new Thread(new Runnable() {@Overridepublic void run() {try {lock.lock();System.out.println("ThreadB获得lock");Thread.sleep(5000);//是await⽅法释放了锁while (num.value <= 3) {//等待3输出完毕的信号reachThreeCondition.await();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();System.out.println("ThreadB释放lock");}try {lock.lock();System.out.println("ThreadB获得lock");//已经收到信号,开始输出4,5,6System.out.println("threadB start write");while (num.value <= 6) {System.out.println(num.value);num.value++;}//4,5,6输出完毕,告诉A线程6输出完了reachSixCondition.signal();} finally {lock.unlock();System.out.println("ThreadB释放lock");}}});//启动两个线程threadB.start();threadA.start();}}View Code创建⽅式:通过Lock创建,Lock.newCondition();常⽤⽅法:await():阻塞,直到相同的Condition调⽤了signal⽅法。
如题,文章主题为“java.util.Scanner的用法”。
在本文中,将对java.util.Scanner类进行全面评估,并探讨其深度和广度的用法,以帮助读者更深入地理解这一主题。
1. Java.util.Scanner类简介java.util.Scanner是Java编程语言中的一个类,它可以用来扫描用户输入,以及从各种数据源中获取输入。
Scanner类提供了一种简便的方式来解析基本类型和字符串,因此在Java编程中被广泛使用。
2. Scanner的基本用法在Java中,我们可以使用Scanner类来获取用户的输入。
我们可以通过以下代码创建一个Scanner对象,并开始扫描用户的输入:```Scanner scanner = new Scanner(System.in);```通过这个简单的示例,我们可以看到Scanner类的基本用法。
它可以从标准输入流中获取用户的输入,并将其解析成不同的数据类型。
3. Scanner的高级用法除了简单的用户输入外,Scanner类还可以用于扫描文件、字符串等不同的数据源。
我们可以使用Scanner类的不同构造函数来指定不同的数据源,比如从文件中读取输入:```File file = new File("input.txt");Scanner scanner = new Scanner(file);```通过这种方式,我们可以利用Scanner类来处理文件输入,而无需编写复杂的输入输出代码。
4. Scanner的原理和内部机制在深入使用Scanner类时,了解它的原理和内部机制是非常重要的。
Scanner类使用了正则表达式来解析输入,因此能够支持复杂的输入格式。
在实际应用中,我们可以通过给Scanner对象指定不同的分隔符和模式来定制化地解析输入。
这为我们处理各种不同格式的输入提供了便利。
5. 总结与回顾在本文中,我们全面评估了java.util.Scanner类的用法。
文章标题:深度剖析Java ConcurrentMap:高效并发操作的利器【导语】在当今信息爆炸的时代,高效并发操作成为了软件开发中的一大挑战。
而Java语言的ConcurrentMap作为高效并发操作的利器,其强大的功能和性能优势备受开发者青睐。
本文将深度剖析Java ConcurrentMap的原理、使用方法和优缺点,带你领略并发编程的魅力。
一、理论基础在并发编程中,线程安全是一个必须被认真对待的问题。
而ConcurrentMap作为Java中线程安全的Map实现,能够保证多线程并发访问时的数据一致性和操作的原子性。
它基于分段锁的机制,将数据分成多个片段,不同的线程可以同时访问不同的片段,从而提高了并发访问的效率。
与传统的HashMap相比,ConcurrentMap能够有效减少锁的竞争,提供更好的性能。
二、使用方法在实际应用中,我们可以通过ConcurrentMap接口的实现类ConcurrentHashMap来进行并发操作。
它提供了丰富的API接口,可以满足多种并发场景下的需求。
put、get、remove等基本操作,以及size、isEmpty等元数据操作。
ConcurrentHashMap还提供了诸如keySet、values、entrySet等视图操作,方便我们对Map进行遍历和操作。
三、性能优势ConcurrentMap在多线程并发访问时能够保持较高的性能。
这得益于它采用了分段锁的机制,不同的线程可以同时操作不同的片段,从而减少了锁的竞争,提高了并发访问的效率。
在元素数量比较大的情况下,ConcurrentMap能够自动扩容,保证操作的高效性。
四、局限性虽然ConcurrentMap在多线程并发访问中有着明显的优势,但也存在一些局限性。
ConcurrentMap并不能保证所有操作的原子性,如putIfAbsent和remove等操作并不是原子性的。
对于一些复合操作,需要我们手动加锁来保证操作的原子性和一致性。
java.io.IOException:你的主机中的软件中⽌了⼀个已建⽴的连接控制台报错如下:org.apache.catalina.connector.ClientAbortException: java.io.IOException: 你的主机中的软件中⽌了⼀个已建⽴的连接。
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:351)at org.apache.catalina.connector.OutputBuffer.flushByteBuffer(OutputBuffer.java:776)at org.apache.catalina.connector.OutputBuffer.append(OutputBuffer.java:681)at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:386)at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:364)at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:96)at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)at org.springframework.util.StreamUtils.copy(StreamUtils.java:147)at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:126)at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:44)at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227)atorg.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:280) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:181)at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:123)at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:450)at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)at .NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)at .SocketProcessorBase.run(SocketProcessorBase.java:49)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)at ng.Thread.run(Thread.java:748)报错原因:使⽤ajax时,form表单提交按钮就没必要设置为submit类型,使⽤普通的button类型就⾏了,否则会出现以上错误信息问题原因:button>在Internet Explorer 的默认类型是 "button",⽽其他浏览器中(包括 W3C 规范)的默认值是 "submit"。
JDK5中的一个亮点就是将Doug Lea的并发库引入到Java标准库中。
Doug Lea确实是一个牛人,能教书,能出书,能编码,不过这在国外还是比较普遍的,而国内的教授们就相差太远了。
一般的服务器都需要线程池,比如Web、FTP等服务器,不过它们一般都自己实现了线程池,比如以前介绍过的Tomcat、Resin和Jetty等,现在有了JDK5,我们就没有必要重复造车轮了,直接使用就可以,何况使用也很方便,性能也非常高。
package concurrent;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class TestThreadPool {public static void main(String args[]) throws InterruptedException {// only two threadsExecutorService exec = Executors.newFixedThreadPool(2);for (int index = 0; index < 100; index++) {Runnable run = new Runnable() {public void run() {long time = (long) (Math.random() * 1000);System.out.println("Sleeping " + time + "ms");try {Thread.sleep(time);} catch (InterruptedException e) {}}};exec.execute(run);}// must shutdownexec.shutdown();}}上面是一个简单的例子,使用了2个大小的线程池来处理100个线程。
concurrentarraylist的基本用法ConcurrentArrayList的基本用法ConcurrentArrayList是Java中一种并发安全的List实现,它是线程安全的,可以同时被多个线程修改和访问。
这种并发安全的List可以在多线程环境中提供更好的性能和效率。
本文将详细介绍ConcurrentArrayList的基本用法,以帮助读者更好地理解和应用这一数据结构。
1. 什么是ConcurrentArrayListConcurrentArrayList是Java中java.util.concurrent包下的一种并发安全的List实现,它继承自Java的ArrayList,并在其基础上提供了线程安全的操作。
ConcurrentArrayList允许多个线程同时对其进行修改和访问,同时保持数据的一致性和正确性。
在多线程并发环境中,使用ConcurrentArrayList可以有效减少线程竞争和加锁的开销,提高程序的执行效率。
2. 创建ConcurrentArrayList对象要使用ConcurrentArrayList,首先需要创建一个ConcurrentArrayList 对象。
可以使用无参构造函数创建一个空的ConcurrentArrayList对象,也可以使用带有初始容量参数的构造函数创建指定初始容量的ConcurrentArrayList对象。
javaimport java.util.concurrent.ConcurrentArrayList;...创建一个空的ConcurrentArrayList对象ConcurrentArrayList<String> list1 = new ConcurrentArrayList<>(); ...创建一个初始容量为10的ConcurrentArrayList对象ConcurrentArrayList<String> list2 = new ConcurrentArrayList<>(10);...3. 添加和删除元素ConcurrentArrayList提供了多种方法来添加和删除元素。
juc应用场景JUC(Java Util Concurrent)是Java语言提供的并发编程库,提供了丰富的线程安全的工具和类,能够有效地支持并发编程。
以下是JUC在实际应用中的一些场景:1.多线程编程:JUC为多线程编程提供了许多有用的工具和类,如线程池(ThreadPoolExecutor)、并发集合(ConcurrentHashMap、ConcurrentLinkedQueue等)、锁(ReentrantLock、ReadWriteLock)、原子变量(AtomicInteger、AtomicReference等)等。
这些工具可以帮助开发者更方便地实现线程安全和高效的多线程应用程序。
2.并发任务处理:JUC的线程池(ThreadPoolExecutor)支持并发任务的执行和管理。
通过线程池,可以有效地管理和调度大量的任务,提高任务执行的效率和性能。
线程池中的线程可以复用,避免频繁地创建和销毁线程,减少了系统开销。
3.并发数据结构:JUC提供了一系列并发安全的数据结构和队列,如ConcurrentHashMap、ConcurrentLinkedQueue、ConcurrentSkipListSet等。
这些数据结构可以在多线程环境中安全地进行读写操作,保证数据的一致性和正确性。
4.同步控制:JUC提供了各种同步控制的机制,如锁、条件变量、信号量等。
这些机制可以帮助开发者实现不同粒度的同步和互斥操作,确保多线程之间的安全协作。
5.原子操作:JUC提供了一系列原子变量类,如AtomicInteger、AtomicLong、AtomicReference等。
这些类可以以原子方式进行读写操作,避免了多线程环境下的竞争条件和数据不一致的问题。
6.并发工具类:JUC提供了许多并发编程中常用的辅助类和工具,如CountDownLatch、CyclicBarrier、Semaphore、LockSupport等。
java.util.concurrent.RejectedExecutionException通过对ThreadPoolExecutor类分析,引发java.util.concurrent.RejectedExecutionException主要有两种原因:1. 线程池显⽰的调⽤了shutdown()之后,再向线程池提交任务的时候,如果你配置的拒绝策略是ThreadPoolExecutor.AbortPolicy的话,这个异常就被会抛出来。
2. 当你的排队策略为有界队列,并且配置的拒绝策略是ThreadPoolExecutor.AbortPolicy,当线程池的线程数量已经达到了maximumPoolSize的时候,你再向它提交任务,就会抛出ThreadPoolExecutor.AbortPolicy异常。
显⽰关闭掉线程池这⼀点很好理解。
⽐如说,你向⼀个仓库去存放货物,⼀开始,仓库管理员把门给你打开了,你放了第⼀件商品到仓库⾥,但是当你放好出去后,有⼈把仓库门关了,那你下次再来存放物品时,你就会被拒绝。
⽰例代码如下:import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class TextExecutor {public ExecutorService fixedExecutorService = Executors.newFixedThreadPool(5);public ExecutorService cachedExecutorService = Executors.newCachedThreadPool();public ExecutorService singleExecutorService = Executors.newSingleThreadExecutor();public void testExecutorException() {for (int i = 0; i < 10; i ++) {fixedExecutorService.execute(new SayHelloRunnable());fixedExecutorService.shutdown();}}private class SayHelloRunnable implements Runnable {@Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {System.out.println("hello world!");}}}public static void main(String[] args) {TextExecutor testExecutor = new TextExecutor();testExecutor.testExecutorException();}}解决⽅案1. 不要显⽰的调⽤shutdown⽅法,例如Android⾥,只有你在Destory⽅法⾥cancel掉AsyncTask,则线程池⾥没有活跃线程会⾃⼰回收⾃⼰。