(友情提示:本博文章欢迎转载,但请注明出处:陈新汉,http://www.blogjava.net/hankchen)
一、并发集合类的选择
同步的集合类Hashtable
和Vector
,以及同步的包装器类Collections.synchronizedMap
和Collections.synchronizedList
,为Map
和List
提供了基本的有条件的线程安全的实现。然而,某些因素使得它们并不适用于具有高度并发性的应用程序中――它们的集合范围的单锁特性对于可伸缩性来说是一个障碍,而且,很多时候还必须在一段较长的时间内锁定一个集合,以防止出现ConcurrentModificationException
s异常。
ConcurrentHashMap
和CopyOnWriteArrayList
实现提供了更高的并发性,同时还保住了线程安全性,只不过在对其调用者的承诺上打了点折扣。ConcurrentHashMap
和CopyOnWriteArrayList
并不是在您使用HashMap
或ArrayList
的任何地方都一定有用,但是它们是设计用来优化某些特定的公用解决方案的。许多并发应用程序将从对它们的使用中获得好处。
总结:在多线程并发情况下,为了避免ConcurrentModificationException
s异常,建议使用ConcurrentHashMap
和CopyOnWriteArrayList
。
还有下面的几个可以考虑:ConcurrentLinkedQueue、CopyOnWriteArraySet、LinkedBlockingQueue、ArrayBlockingQueue
二、高效的乘除运算
服务器计算时,对于乘除运算,采用下面的方式:
A*2=a<<1
A/2=a>>1
这样可以提高运算效率。
三、原子自增器
多线程环境下,
AtomicInteger
可用在应用程序中(如以原子方式增加的计数器),并且不能用于替换
Integer
。但是,此类确实扩展了
Number
,允许那些处理基于数字类的工具和实用工具进行统一访问。
例如:
private AtomicInteger bomdIdCreator = new AtomicInteger(); //自增序列号
/**
*得到新的ID,保持自增
*@return
*/
public int getNewBombID(){
return bomdIdCreator.addAndGet(1);
}
四、多线程锁机制实现
多线程环境下,为了避免资源竞争,引入了锁机制。一般实现锁机制有下面几种方法:
1.
同步方法、同步块:
synchronized
2.
监视器方法:(
wait
、
notify
和
notifyAll
)
3. ReentrantLock
注意:ReentrantLock是一个可重入的互斥锁
Lock
,它具有与使用
synchronized
方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
例如:建议总是立即实践,使用
lock
块来调用
try
,在之前
/
之后的构造中,最典型的代码如下:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
五、线程池的实现方式
Doug Lea
编写了一个优秀的并发实用程序开放源码库
util.concurrent
,它包括互斥、信号量、诸如在并发访问下执行得很好的队列和散列表之类集合类以及几个工作队列实现。该包中的
ThreadPoolExecutor
类是一种有效的、广泛使用的以工作队列为基础的线程池的正确实现。您无须尝试编写您自己的线程池,这样做容易出错,相反您可以考虑使用
util.concurrent
中的一些实用程序。
线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行集合任务时使用的线程)的方法。
强烈建议程序员使用较为方便的
Executors
工厂方法
Executors.newCachedThreadPool()
(无界线程池,可以进行自动线程回收)、
Executors.newFixedThreadPool(int)
(固定大小线程池)和
Executors.newSingleThreadExecutor()
(单个后台线程),它们均为大多数使用场景预定义了设置。
例如:
public class ThreadPoolExecutorTest {
final static ExecutorService threadPool=Executors.newCachedThreadPool(); //简单线程池实现
/**
* @param args
*/
public static void main(String[] args) {
for(int i=0;i<10;i++){
threadPool.execute(new Runnable(){
public void run() {
System.out.println("aaa"+this.getClass().getName());
//do other things
}
});
}
}
}
六、实现定时任务的几种方式比较
1.
使用原始的
Timer
类
2. ScheduledThreadPoolExecutor
(
JDK 1.5
新增)
3. Quatz
开源项目
从
Java 5.0
开始,
java.util.concurrent
包中增加了一个
ScheduledThreadPoolExecutor
类,用来实现定时任务和线程池的管理,比起
Timer
简陋的实现是要强大得多。利用
ScheduledThreadPoolExecutor
的
scheduleAtFixedRate()
和
scheduleWithFixedDelay()
两个方法就可以实现任务调度的基本功能,从前用
Timer
实现的功能应该要迁移到
scheduleWithFixedDelay()
上了。
注意:
ScheduledThreadPoolExecutor
是实现
ScheduledExecutorService
接口的具体类。
1)public static final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(2);
2)public static final ScheduledThreadPoolExecutor scheduledExecutor=new ScheduledThreadPoolExecutor(2);
这两种方式是一样的,都是得到一个可调度的线程池。
ScheduledThreadPoolExecutor
与
Timer
的区别:
1.
Timer
的主要方法有:
//
安排在指定的时间执行
void schedule(TimerTask task, Date time)
//
安排在指定的时间开始以
重复的延时
执行
void schedule(TimerTask task, Date firstTime, long period)
//
安排在指定的延迟后执行
void schedule(TimerTask task, long delay)
//
安排在指定的延迟后开始以重复的延时执行
void schedule(TimerTask task, long delay, long period)
//
安排在指定的时间开始以
重复的速率
执行
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
//
安排在指定的延迟后开始以重复的速率执行
void scheduleAtFixedRate(TimerTask task, long delay, long period)
注:
重复的延时
和
重复的速率
的区别在于,前者是在前一个任务的执行结束后间隔
period
时间再开始下一次执行;而
scheduleAtFixedRate
则是会尽量按照任务的初始时间来按照间隔
period
时间执行。如果一次任务执行由于某些原因被延迟了,用
schedule()
调度的后续任务同样也会被延迟,而用
scheduleAtFixedRate()
则会快速的开始两次或者多次执行,是后续任务的执行时间能够赶上来。
2.
ScheduledThreadPoolExecutor
的主要方法:
//
在指定的延迟后执行
<V>ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
//
在指定的延迟后执行
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
//
在指定的延迟后以固定速率执行
(
类似
Timer.scheduleAtFixedRate())
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
//
在指定的延迟后以固定间隔执行
(
类似
Timer.schedule())
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
比较:
(
1
)
Timer
对调度的支持是基于绝对时间的,因此任务对系统时间的改变是敏感的;而
ScheduledThreadPoolExecutor
支持相对时间。
(
2
)
Timer
使用单线程方式来执行所有的
TimerTask
,如果某个
TimerTask
很耗时则会影响到其他
TimerTask
的执行;而
ScheduledThreadPoolExecutor
则可以构造一个固定大小的线程池来执行任务。
(
3
)
Timer
不会捕获由
TimerTask
抛出的未检查异常,故当有异常抛出时,
Timer
会终止,导致未执行完的
TimerTask
不再执行,新的
TimerTask
也不能被调度;
ScheduledThreadPoolExecutor
对这个问题进行了妥善的处理,不会影响其他任务的执行。
结论:
Timer
有这么多的缺点,如果是使用
JDK1.5
以上的话,应该没什么理由要使用
Timer
来进行调度。
(友情提示:本博文章欢迎转载,但请注明出处:陈新汉,http://www.blogjava.net/hankchen)
分享到:
相关推荐
6. 多线程和并发:Java提供了一套内建的线程支持,让程序能够同时执行多个任务,这对于提高应用程序的性能非常重要。 7. 网络编程:网络编程部分可能会涉及到Java的Socket编程,学习如何编写客户端和服务器端程序,...
API(Application Programming Interface)是软件开发中的一个重要概念,它是一系列预先定义的函数、类、接口和协议,用于构建特定功能的应用程序。本压缩包包含了针对JDK(Java Development Kit)和JavaScript这两...
Spring Framework 是一个广泛使用的Java应用程序开发框架,尤其在企业级应用中占据主导地位。这个"最新版spring-framework-5.0.1.RELEASE-dist完整包"包含了Spring框架的第五个主要版本的首个次要更新,提供了许多...
通过以上步骤,我们便可以在Eclipse环境中搭建起一个具备完整性能监控能力的开发平台,利用TPTP对运行在Tomcat上的Java应用程序进行全面的性能测试和调优。这对于提升应用的运行效率、减少资源消耗、提高用户体验等...
CodeFusion 是一款强大的开发工具,专为创建和管理基于Adobe ColdFusion的应用程序而设计。这个框架结合了高效能、可扩展性以及便捷的开发流程,极大地提升了开发者的工作效率。在本文中,我们将深入探讨CodeFusion...
易语言5.1 相对于易语言5.0更新说明: 支持静态链接其它编程语言(如C/C++、汇编等)编译生成的静态库(.LIB或.OBJ),但仅限于COFF格式,支持cdecl和stdcall两种函数调用约定。 使用说明如下:函数声明和调用...
将这三个框架整合起来,不仅可以发挥各自的优点,还能相互补充,从而实现更为高效和稳定的Web应用开发流程。 1. **提高开发效率**:Spring的依赖注入和面向切面编程特性使得代码更加清晰和可维护,而Hibernate则...
- **多语言支持:** 支持多种编程语言,如PHP、Java、Python等,便于开发复杂的Web应用程序。 - **API接口设计:** 提供RESTful API接口,便于前端与后端之间的数据交换。 - **性能监控:** 利用MySQL提供的工具监控...