关于 java.util.concurrent 您不知道的 5 件事

合集下载

java juc详解

java juc详解

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异常问题详解

java.util.ConcurrentModificationException异常问题详解

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包下常见类的使用

Java并发编程之java.util.concurrent包下常见类的使用

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的用法

如题,文章主题为“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:高效并发操作的利器【导语】在当今信息爆炸的时代,高效并发操作成为了软件开发中的一大挑战。

而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:你的主机中的软件中止了一个已建立的连接

java.io.IOException:你的主机中的软件中止了一个已建立的连接

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"。

教你java.util.concurrent多线程框架

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的基本用法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应用场景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

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,则线程池⾥没有活跃线程会⾃⼰回收⾃⼰。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
System.out.println("Interrupted! " + "Last one out, turn out the lights!");
} } }
class Consumer implements Runnable
{ private BlockingQueue<String> drop; public Consumer(BlockingQueue<String> d) { this.drop = d; }
回页首
2. CopyOnWriteArrayList
创建数组的全新副本是过于昂贵的操作,无论是从时间上,还是从内存开销上,因此在通常使用中很少考虑;开发人 员往往求助于使用同步的 ArrayList。然而,这也是一个成本较高的选择,因为每当您跨集合内容进行迭代时,您 就不得不同步所有操作,包括读和写,以此保证一致性。
Concurrent Collections 是 Java™ 5 的巨大附加产品,但是在关于注释和泛型的争执中很多 Java 开发人员忽视了它 们。此外(或者更老实地说),许多开发人员避免使用这个数据包,因为他们认为它一定很复杂,就像它所要解决的 问题一样。
事实上,java.util.concurrent 包含许多类,能够有效解决普通的并发问题,无需复杂工序。阅读本文,了解 java.util.concurrent 类,比如 CopyOnWriteArrayList 和 BlockingQueue 如何帮助您解决多线程编程 的棘手问题。
页码,1/7
关于 java.util.concurrent 您不知道的 5 件事,第 1 部分
通过并发 Collections 进行多线程编程
简介: 编写能够良好执行,防止应用程序受损的多线程代码是很艰巨的任务 — 这也是为什么我们需要 java.util.concurrent 的原因。Ted Neward 会向您说明并发 Collections 类,比如 CopyOnWriteArrayList,BlockingQueue,还有 ConcurrentMap,如何针对您的并发编程需求改进标准 Collections 类。
1. TimeUnit
尽管本质上 不是 Collections 类,但 java.util.concurrent.TimeUnit 枚举让代码更易读懂。使用 TimeUnit 将使用您的方法或 API 的开发人员从毫秒的 “暴政” 中解放出来。
TimeUnit 包括所有时间单位,从 MILLISECONDS 和 MICROSECONDS 到 DAYS 和 HOURS,这就意味着它能够处 理一个开发人员所需的几乎所有的时间范围类型。同时,因为在列举上声明了转换方法,在时间加快时,将 HOURS 转换回 MILLISECONDS 甚至变得更容易。
尽管 Guarded Blocks 教程中的代码有效,但是它耗时久,混乱,而且也并非完全直观。退回到 Java 平台较早的时 候,没错,Java 开发人员不得不纠缠于这种代码;但现在是 2010 年 — 情况难道没有改善?
清单 1 显示了 Guarded Blocks 代码的重写版,其中我使用了一个 ArrayBlockingQueue,而不是手写的 Drop。
回页首
3. BlockingQueue
BlockingQueue 接口表示它是一个 Queue,意思是它的项以先入先出(FIFO)顺序存储。在特定顺序插入的项以 相同的顺序检索 — 但是需要附加保证,从空队列检索一个项的任何尝试都会阻塞调用线程,直到这个项准备好被检 索。同理,想要将一个项插入到满队列的尝试也会导致阻塞调用线程,直到队列的存储空间可用。
页ngQueue 还体现了“公平” — 意思是它为读取器和编写器提供线程先入先出访问。这种替代方法是 一个更有效,但又冒穷尽部分线程风险的政策。(即,允许一些读取器在其他读取器锁定时运行效率更高,但是您可 能会有读取器线程的流持续不断的风险,导致编写器无法进行工作。) 注意 Bug! 顺便说一句,如果您注意到 Guarded Blocks 包含一个重大 bug,那么您是对的 — 如果开发人员在 main() 中的 Drop 实例上同步,会出现什么情况呢? BlockingQueue 还支持接收时间参数的方法,时间参数表明线程在返回信号故障以插入或者检索有关项之前需要阻 塞的时间。这么做会避免非绑定的等待,这对一个生产系统是致命的,因为一个非绑定的等待会很容易导致需要重启 的系统挂起。
本文的标签: 多线程, 应用开发
标记本文!
发布日期: 2010 年 7 月 07 日 (最初发布 2010 年 7 月 01 日) 级别: 初级 其他语言版本: 英文
关于本系列
您觉得自己懂 Java 编程?事实是,大多数开发人员都只领会到了 Java 平台的皮毛,所学也只够应付工作。在本 系 列 中,Ted Neward 深度挖掘 Java 平台的核心功能,揭示一些鲜为人知的事实,帮助您解决最棘手的编程困难。
清单 1. BlockingQueue
import java.util.*; import java.util.concurrent.*;
class Producer implements Runnable
{ private BlockingQueue<String> drop; List<String> messages = Arrays.asList( "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "Wouldn't you eat ivy too?");
System.out.println("Interrupted! " + "Last one out, turn out the lights!");
} } }
public class ABQApp {
public static void main(String[] args) {
BlockingQueue<String> drop = new ArrayBlockingQueue(1, true); (new Thread(new Producer(drop))).start(); (new Thread(new Consumer(drop))).start(); } }
System.out.println("Interrupted! " + "Last one out, turn out the lights!");
} } }
class Consumer implements Runnable
{ private BlockingQueue<String> drop; public Consumer(BlockingQueue<String> d) { this.drop = d; }
public void run() {
try {
String msg = null; while (!((msg = drop.take()).equals("DONE")))
BlockingQueue 干净利落地解决了如何将一个线程收集的项“传递”给另一线程用于处理的问题,无需考虑同步问 题。Java Tutorial 的 Guarded Blocks 试用版就是一个很好的例子。它构建一个单插槽绑定的缓存,当新的项可用, 而且插槽也准备好接受新的项时,使用手动同步和 wait()/notifyAll() 在线程之间发信。(详见 Guarded Blocks 实现。)
页码,2/7
这又让成本结构回到这样一个场景:需多读者都在读取 ArrayList,但是几乎没人会去修改它。
CopyOnWriteArrayList 是个巧妙的小宝贝,能解决这一问题。它的 Javadoc 将 CopyOnWriteArrayList 定 义为一个 “ArrayList 的线程安全变体,在这个变体中所有易变操作(添加,设置等)可以通过复制全新的数组来 实现”。
public Producer(BlockingQueue<String> d) { this.drop = d; }
public void run() {
try {
for (String s : messages) drop.put(s);
drop.put("DONE"); } catch (InterruptedException intEx) {
public Producer(BlockingQueue<String> d) { this.drop = d; }
public void run() {
try {
for (String s : messages) drop.put(s);
drop.put("DONE"); } catch (InterruptedException intEx) {
集合从内部将它的内容复制到一个没有修改的新数组,这样读者访问数组内容时就不会产生同步成本(因为他们从来 不是在易变数据上操作)。
本质上讲,CopyOnWriteArrayList 很适合处理 ArrayList 经常让我们失败的这种场景:读取频繁,但很少有 写操作的集合,例如 JavaBean 事件的 Listeners。
public void run() {
try {
String msg = null; while (!((msg = drop.take()).equals("DONE")))
System.out.println(msg); } catch (InterruptedException intEx) {
相关文档
最新文档