線程雖然在web開發中用的不算特別多,但在特定的情況下還是能發揮重要重要作用的,因此即使用的少還是掌握下比較好;下面先回顧下比較線程的常規實現方法
1 繼承Thread類
2 實現runnable接口(使用較多)
java5之後有了新的線程實現方式,java5可以使用Executor來啓動線程,效率更好;這次主要從Executor執行runnable任務、callable任務、自定義線程池三個方面進行學習分享
一 Executor執行runnable任務、callable任務
callable任務相比runnable任務的區別在於它有返回值,每個任務執行後可以通過Future返回結果
1 Executor執行runnable任務(打印執行的任務和負責執行的線程名稱)
package com.debug;
import java.util.concurrent.*;
public class Executor01 {
public static void main(String aargs[]){
//ExecutorService pool=Executors.newFixedThreadPool(5);固定數目線程池
//ExecutorService pool=Executors.newSingleThreadExecutor();單例線程池
ExecutorService executorService=Executors.newCachedThreadPool();//緩存型池子
for (int i = 1; i <= 5; i++){
executorService.execute(new Executor01Runnable(i));
}
executorService.shutdown();
}
}
class Executor01Runnable implements Runnable{
private int task;
public Executor01Runnable(int task){
this.task=task;
}
public void run(){
System.out.println("第"+task+"個任務被"+Thread.currentThread().getName() + "線程執行了");
}
}
執行的結果截圖如下所示:
2 Executor執行callable任務
runnable任務執行使用execute方法,但callable使用submit;
submit 也是首先選擇空閒線程來執行任務,如果沒有,纔會創建新的線程來執行任務。另外,需要注意:如果Future的返回尚未完成,則get()方法會阻塞等待,直到Future完成返回,可以通過調用isDone()方法判斷Future是否完成了返回。
package com.debug;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.*;
public class UseCallable {
public static void main(String aargs[]){
ExecutorService pool=Executors.newCachedThreadPool();
List<Future<String>> arr=new ArrayList<Future<String>>();
for(int i=1;i<=10;i++){
Future<String> res=pool.submit(new ThreadTaskWithResult(i));
arr.add(res);
}
Iterator<Future<String>> it=arr.iterator();
while(it.hasNext()){
Future<String> result=it.next();
try {
System.out.println(result.get());
//System.out.println(result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
pool.shutdown();
}
}
// pool.shutdown();
}
}
class ThreadTaskWithResult implements Callable<String> {
private int count;
public ThreadTaskWithResult(int count){
this.count=count;
}
public String call() throws Exception {
System.out.println("call()方法被自動調用!!! " + Thread.currentThread().getName());
return "第"+count+"個任務執行完畢,執行任務的線程是:"+Thread.currentThread().getName();
}
}
執行的結果截圖如下所示:
二 自定義線程池
package com.debug;
import java.util.concurrent.*;
public class CustomThreadPool {
public static void main(String args[]) throws Exception{
//創建等待隊列
BlockingQueue<Runnable> block=new ArrayBlockingQueue<Runnable>(30);
//創建線程池,最小3個,最大10個
ThreadPoolExecutor pool=new ThreadPoolExecutor(3,5,1000, TimeUnit.MILLISECONDS,block);
pool.execute(new CustomRunnable());
pool.execute(new CustomRunnable());
pool.execute(new CustomRunnable());
pool.execute(new SpecilCustomRunnable());
pool.execute(new SpecilCustomRunnable());
pool.shutdown();
}
}
class CustomRunnable implements Runnable{
public void run(){
System.out.println("CustomRunnable "+Thread.currentThread().getName() + "線程被調用了。");
}
}
class SpecilCustomRunnable implements Runnable{
public void run(){
System.out.println("SpecilCustomRunnable "+Thread.currentThread().getName() + "線程被調用了。");
for(int i=1;i<5;i++){
System.out.println("SpecilCustomRunnable "+Thread.currentThread().getName() + "循環執行到第"+i+"次");
}
}
}
文章可能寫的潦草,只能算自己的隨筆和摘抄,大部分靈感都來源於下面這篇博客,可以順帶看一看