線程
線程的四種狀態
- New:線程剛剛創建,還未加入線程調度
- Runnable:就緒態,調用 start() 后,線程加入線程調度。此時,只要獲取到 CPU 時間片,就會進入運行態
- Running:運行態,線程獲取到 CPU 時間片后,就會被 CPU 運行。可以通過 yield() 主動讓出時間片,會使得線程返回就緒態
- Blocked:阻塞態,此時線程需要等待釋放信號才能進入就緒態,如等待用戶輸入、等待鎖被解除
- Dead:線程結束
線程中的變量
// 獲取當前線程Thread thread = Thread.currentThread();
// 獲取線程 IDlong id = thread.getId();
// 獲取線程 Name String name = thread.getName();
// 獲取線程優先級int priority = thread.getPriority();
publicfinalstaticint MIN_PRIORITY = 1;
publicfinalstaticint NORM_PRIORITY = 5;
publicfinalstaticint MAX_PRIORITY = 10;
// 判定線程是否為守護線程boolean isDaemon = thread.isDaemon();
// 判定線程是否被中斷;被中斷會進入阻塞 Blocked 狀態boolean isInterrupted = thread.isInterrupted();
// 判定線程是否存活boolean isAlive = thread.isAlive();
創建線程的方式
- 繼承Thread類
- 實現Runnable接口
- 實現Callable接口
- 使用線程池創建
1.submit和excute有什么區別
submit支持實現Runnable和Callable接口的線程不調用Future的get()方法會吃掉異常
excute只支持Runnable接口的現場
public class ThreadStudy {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Thread1 tread1 = new Thread1();
tread1.setName("線程一");
tread1.start();
Thread thread2 = new Thread(new Thread2());
thread2.setName("線程二");
thread2.start();
FutureTask<String> task = new FutureTask<String>(new Thread3());
Thread thread3 = new Thread(task);
thread3.setName("線程三");
thread3.start();
ExecutorService executorService = Executors.newFixedThreadPool(2);
System.out.println("-----------------------");
executorService.execute(new Thread2());
executorService.execute(new Thread1());
executorService.submit(new Thread3());
Future<String> submit = executorService.submit(new Thread3());
String result = submit.get();
System.out.println(result);
Executors.newCachedThreadPool();
Executors.newSingleThreadExecutor();
executorService.shutdown();
}
}
class Thread1 extends Thread{
@Override
public void run() {
System.out.println("這是繼承Thread創建的線程:"+Thread.currentThread().getName());
}
}
class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("這是實現Runnable創建的線程:"+Thread.currentThread().getName());
}
}
class Thread3 implements Callable {
@Override
public String call() throws Exception {
System.out.println("這是實現Callable創建的線程:"+Thread.currentThread().getName());
return "這是實現Callable創建的線程:"+Thread.currentThread().getName();
}
}
線程池創建的線程
public ThreadPoolExecutor(int corePoolSize, // 核心線程池大小
int maximumPoolSize, // 最大線程池大小
long keepAliveTime, // 線程最大空閑時間
TimeUnit unit, // 時間單位
BlockingQueue<Runnable> workQueue, // 線程等待隊列
ThreadFactory threadFactory, // 線程創建工程
RejectedExecutionHandler handler ) { //拒絕策列
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
-
newFixedThreadPool
-
參數分析:核心線程數和最大線程數相同,線程等待隊列無限大
-
使用場景:Web服務器瞬間削峰,持續高峰情況需要注意隊列阻塞
-
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
-
newCacheThreadPool
-
參數分析:核心線程池為0,最大線程數無限大,線程最大空閑時間60秒
-
使用場景:快速處理大量耗時較短的任務,如Netty的NIO接受請求時,可使用CachedThreadPool。
-
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
-
newSchedulThreadPool
參數分析:傳入核心線程
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
-
newSingeThreadExecutor
參數分析:依靠FinalizableDelegatedExecutorService執行操作
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
static class FinalizableDelegatedExecutorService
extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
protected void finalize() {
super.shutdown();
}
}
-
newSingThreadSchedulExecutor
參數:線程工廠
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1, threadFactory));
}
static class DelegatedScheduledExecutorService
extends DelegatedExecutorService
implements ScheduledExecutorService {
private final ScheduledExecutorService e;
DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
super(executor);
e = executor;
}
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return e.schedule(command, delay, unit);
}
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
return e.schedule(callable, delay, unit);
}
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return e.scheduleAtFixedRate(command, initialDelay, period, unit);
}
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
}
自定義線程池
public class ThreadTest {
public static void main(String[] args) throws InterruptedException, IOException {
int corePoolSize = 2;
int maximumPoolSize = 4;
long keepAliveTime = 10;
TimeUnit unit = TimeUnit.SECONDS;
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
ThreadFactory threadFactory = new NameTreadFactory();
RejectedExecutionHandler handler = new MyIgnorePolicy();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
workQueue, threadFactory, handler);
executor.prestartAllCoreThreads(); // 預啟動所有核心線程
for (int i = 1; i <= 10; i++) {
MyTask task = new MyTask(String.valueOf(i));
executor.execute(task);
}
System.in.read(); //阻塞主線程
}
static class NameTreadFactory implements ThreadFactory {
private final AtomicInteger mThreadNum = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "my-thread-" + mThreadNum.getAndIncrement());
System.out.println(t.getName() + " has been created");
return t;
}
}
public static class MyIgnorePolicy implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
doLog(r, e);
}
private void doLog(Runnable r, ThreadPoolExecutor e) {
// 可做日志記錄等
System.err.println( r.toString() + " rejected");
// System.out.println("completedTaskCount: " + e.getCompletedTaskCount());
}
}
static class MyTask implements Runnable {
private String name;
public MyTask(String name) {
this.name = name;
}
@Override
public void run() {
try {
System.out.println(this.toString() + " is running!");
Thread.sleep(3000); //讓任務執行慢點
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String getName() {
return name;
}
@Override
public String toString() {
return "MyTask [name=" + name + "]";
}
}
}
線程池的大小
IO密集型
CPU密集型
Runtime.getRuntime().availableProcessors():獲取CPU的核數
結論
總結,通過自定義線程池,我們可以更好的讓線程池為我們所用,更加適應我的實際場景。