1.自己实现多线程异步发送消息
/**
自定义线程executor,这里workQueue使用ArrayBlockQueue:是一个有界的阻塞队列,其内部是通过一个数组来维护的,该队列采用FIFO的原则对元素进行排序添加的。可以选用多种queue如:LinkedBlockingQuene、SynchronousQuene、PriorityBlockingQueue
**/
private static int coreSize = Runtime.getRuntime().availableProcessors();
public static ExecutorService senderAsync = new ThreadPoolExecutor(coreSize , coreSize , 60L, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10000), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread();
thread.setName("异步发送消息");
return thread;
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.error("runnable{},executor{}", r, executor);
}
});
/**
* 提交开启线程
* @param r
*/
public static void submit(Runnable r) {
senderAsync.submit(r);
}
public static void main(String[] args) {
//测试代码
senderAsync.submit((Runnable) () -> {
System.out.println("发送消息");
});
}
2.Executors.newFixedThreadPool
创建固定数目线程的线程池,任意时间点,最多只能有固定数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,直到当前的线程中某个线程终止直接被移出池子
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("fixedThreadPool");
return thread;
}
});
3.Executors.newCachedThreadPool
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
newCachedThreadPool 使用了SynchronousQueue是一个内部只能包含一个元素的队列。插入元素到队列的线程被阻塞,直到另一个线程从队列中获取了队列中存储的元素。同样,如果线程尝试获取元素并且当前不存在任何元素,则该线程将被阻塞,直到线程将元素插入队列。
4.Executors.newScheduledThreadPool
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
newScheduledThreadPool使用了DelayedWorkQueue,该队列是定制的优先级队列,只能用来存储RunnableScheduledFutures任务。堆是实现优先级队列的最佳选择,而该队列正好是基于堆数据结构的实现。
5.newSingleThreadExecutor
创建一个单线程化的Executor。
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
newSingleThreadExecutor中创建一个LinkedBlockingQueue队列,LinkedBlockingQueue内部由单链表实现,只能从head取元素,从tail添加元素。添加元素和获取元素都有独立的锁,也就是说LinkedBlockingQueue是读写分离的,读写操作可以并行执行。LinkedBlockingQueue采用可重入锁(ReentrantLock)来保证在并发情况下的线程安全。