java自定义线程池池,线程池使用及自定义线程池
一 案例引申
編寫代碼同時(shí)只允許五個線程并發(fā)訪問(以下文的函數(shù)為例子)
private static void method() {
System.out.println("ThreadName" + Thread.currentThread().getName() + "進(jìn)來了");
Thread.sleep(2000);
System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");
}
思考:
1 若果使用 synchronized的話避免了并發(fā)安全問題,但是不滿足題目的要求,因?yàn)轭}目要求一次讓五個線程訪問,使用鎖的時(shí)候一次只能訪問一個。
2 解決思路:使用信號量或者使用線程池
二 信號量的簡單使用(了解)
package ThreadPool;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Create by SunnyDay on 2018/11/27
*/
public class ThreadPoolDemo {
//信號量 Doug Lea 大牛寫的(concurrent并發(fā)包下面的東西都是他寫的) 參數(shù)控制并發(fā)線程的個數(shù)
private static Semaphore semaphore = new Semaphore(5);
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
method();
} catch (InterruptedException e) {
}
}
}).start();
}
private static void method() throws InterruptedException {
// 首先獲取一把鎖
semaphore.acquire();
System.out.println("ThreadName" + Thread.currentThread().getName() + "進(jìn)來了");
Thread.sleep(2000);
System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");
// 釋放鎖
semaphore.release();
}
三 使用線程池解決(了解)
package ThreadPool;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Create by SunnyDay on 2018/11/27
* 使用線程池解決
*/
public class ThreadPool {
/**
* java 提供了線程池的創(chuàng)建工具類( Executors),
* 我們可以通過工具類創(chuàng)建不同的線程池
*/
private static Executor executor = Executors.newCachedThreadPool();//緩沖線程池
private static Executor executor2 = Executors.newFixedThreadPool(5);//固定線程池
private static Executor executor3 = Executors.newScheduledThreadPool(5);//計(jì)劃任務(wù)線程池
private static Executor executor4 = Executors.newSingleThreadExecutor();//單個線程池(池中只有一個線程)
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
// 線程池的簡單使用(十分簡單) 調(diào)用execute方法傳遞參數(shù)類型為runnable類型即可
executor2.execute(new Runnable() {
@Override
public void run() {
try {
method();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
private static void method() throws InterruptedException {
System.out.println("ThreadName" + Thread.currentThread().getName() + "進(jìn)來了");
Thread.sleep(2000);
System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");
}
}
四 自定義線程池
1 小發(fā)現(xiàn)
/**
* 查看隨便幾個個線程池的源碼:
* public static ExecutorService newCachedThreadPool() {
* return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
* 60L, TimeUnit.SECONDS,
* new SynchronousQueue());
* }
*
* 發(fā)現(xiàn)都是對線程池類(ThreadPoolExecutor)進(jìn)行了簡單的封裝(傳的參數(shù)不一致)
*/
2 ThreadPoolExecutor構(gòu)造( 以6個參數(shù)的為例子)
* @param corePoolSize 核心池大小 int
* @param maximumPoolSize 最大池大小 int
* @param keepAliveTime 保活時(shí)間 long(任務(wù)完成后要銷毀的延時(shí))
* @param unit 時(shí)間單位 決定參數(shù)3的單位,枚舉類型的時(shí)間單位
* @param workQueue 工作隊(duì)列 用于存儲任務(wù)的工作隊(duì)列(BlockingQueue接口類型)
* @param threadFactory 線程工廠 用于創(chuàng)建線程
*
* */
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
3 自定義實(shí)現(xiàn)案例
package ThreadPool;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Create by SunnyDay on 2018/11/27
*/
public class ThreadPoolDemo {
public static void main(String[] args) {
/**手寫線程池
* @param corePoolSize 核心池大小 int
* @param maximumPoolSize 最大池大小 int
* @param keepAliveTime 保活時(shí)間 long(任務(wù)完成后要銷毀的延時(shí))
* @param unit 時(shí)間單位 決定參數(shù)3的單位,枚舉類型的時(shí)間單位
* @param workQueue 工作隊(duì)列 用于存儲任務(wù)的工作隊(duì)列(BlockingQueue接口類型)
* @param threadFactory 線程工廠 用于創(chuàng)建線程
*
*線程不是越多越好,google工程師推薦 線程個數(shù)=cpu核心數(shù)+1(例如四核的開5個線程最好)
* */
// 參數(shù)任務(wù)上限
LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue<>(100);
ThreadFactory threadFactory = new ThreadFactory() {
// int i = 0; 用并發(fā)安全的包裝類
AtomicInteger atomicInteger = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
//創(chuàng)建線程 吧任務(wù)傳進(jìn)來
Thread thread = new Thread(r);
// 給線程起個名字
thread.setName("MyThread" + atomicInteger.getAndIncrement());
return thread;
}
};
ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 10, 1, TimeUnit.SECONDS, blockingQueue, threadFactory);
for (int i = 0; i < 100; i++) {
pool.execute(new Runnable() {
@Override
public void run() {
try {
method();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
/**
* 編寫代碼(如下文的函數(shù))同時(shí)只允許五個線程并發(fā)訪問:
*
* 1 若果使用 synchronized的話避免了并發(fā)安全問題,但是不滿足題目的要求,
* 因?yàn)轭}目要求一次讓五個線程訪問,使用鎖的時(shí)候一次只能訪問一個。
* 2 解決思路:使用信號量或者使用線程池
*
* 3 自己手動封裝線程池(明白啟動策略)
*/
private static void method() throws InterruptedException {
System.out.println("ThreadName" + Thread.currentThread().getName() + "進(jìn)來了");
Thread.sleep(2000);
System.out.println("ThreadName" + Thread.currentThread().getName() + "出去了");
}
}
五 線程池補(bǔ)充
1 啟動策略草圖
image.png
2 流程圖(摘抄)
image.png
六 總結(jié)
通過上面的總結(jié)相信對線程池的概念,使用,啟動策略,大致的有了一些了解,但是這些還是不夠的,想要深入了解還需我們不懈的努力探討!!!
總結(jié)
以上是生活随笔為你收集整理的java自定义线程池池,线程池使用及自定义线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql语句数据库_数据库的Mysql
- 下一篇: html5滑动删除置顶,html5向左滑