1.1 shutdown() 和 shutdownNow()
方法shutdown()的作用是使當前未執行完的線程繼續執行,而不再添加新的任務,
shutdown()方法是不阻塞的。
方法shutdownNow()的作用是中斷所有的任務,並且拋出InterruptdException
異常(需要和任務中的if(Thread.currentThread().isInterrupted() == true) 結合使用)。
未執行的線程不再執行,也從執行隊列中清除。
2.1 工廠ThreadFactory + UncaughtExceptionHandler 處理異常
可以通過重寫ThreadFactory 中的newThread(Runnable r)方法來對線程的一些屬性進行定製化。
2.2 代碼
package com.lhc.concurrent.executor.factory;
import java.util.Date;
import java.util.concurrent.ThreadFactory;
public class MyTHreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("name:" + new Date());
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("自定義處理異常");
System.out.println(t.getName() + ":" + e.getMessage());
e.printStackTrace();
}
});
return thread;
}
}
2.3 測試類
package com.lhc.concurrent.executor.factory;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis());
//拋出異常
String str = null;
System.out.println(str.contains(""));
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis());
}
public static void main(String[] srgs){
MyRunnable myRunnable = new MyRunnable();
ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 8, 20, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>());
executor.setThreadFactory(new MyTHreadFactory());
executor.execute(myRunnable);
}
}
2.4運行結果
name:Mon May 13 17:16:57 GMT+08:00 2019 1557739017491
java.lang.NullPointerException
自定義處理異常
name:Mon May 13 17:16:57 GMT+08:00 2019:null
at com.lhc.concurrent.executor.factory.MyRunnable.run(MyRunnable.java:13)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at
java.lang.Thread.run(Thread.java:745)
3.1 方法afterExecute() 和 beforeExecute()
在線程池ThreadPoolExecutor 類中重寫這兩個方法可以對線程池中執行的線程對象實現監控。
3.2 代碼
package com.lhc.concurrent.executor.before;
public class MyThread extends Thread{
public MyThread(String name) {
super();
this.setName(name);
}
@Override
public void run() {
System.out.println("打印了! begin" + this.getName() + " " + System.currentTimeMillis());
try {
Thread.sleep(4000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("打印了! end" + this.getName() + " " + System.currentTimeMillis());
}
}
3.3 測試類
package com.lhc.concurrent.executor.before;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPool extends ThreadPoolExecutor{
public MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
System.out.println(((MyThread)r).getName() + "準備執行");
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
System.out.println(((MyThread)r).getName() + "執行完畢");
}
public static void main(String[] args){
MyThreadPool myThreadPool = new MyThreadPool(2, 2, Integer.MAX_VALUE,
TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
myThreadPool.execute(new MyThread("0001"));
myThreadPool.execute(new MyThread("0002"));
myThreadPool.execute(new MyThread("0003"));
myThreadPool.execute(new MyThread("0004"));
}
}
4.1 方法execute() 與submit的區別
1) 方法execute() 沒有返回值,而submit()方法可以有返回值
2) 方法execute() 在默認的情況下異常直接拋出,不能捕獲,但可以通過自定義ThreadFactory 的方式進行捕獲,而submit()方法在默認的情況下,可以
捕獲異常。