最近做郵件傳送功能時,客戶端操作程式等待時長,有時候會很長甚至會死執行緒,這個很不利於使用者的體驗,為了解決這個問題,我想到了使用多執行緒,讓系統在後台傳送郵件,使用者操作介面不受影響,從而保證使用者體驗軟體的流暢度。事實上完成後的效果還不錯,系統介面瞬間響應,郵件後台傳送,其快慢程度取決於郵件伺服器響應速率和網路!
下面說說我研究多執行緒的方法和心得。研究時我為了便捷,只做了檔案複製的demo,然後再將功能**移植到開發系統的郵件傳送功能中,這樣做是為了保證系統的安全性。
首先要知道使用多執行緒有兩種方法,一是繼承thread類,一種是實現runnable介面。由於繼承的侷限性,只能單繼承,所以一般情況下會先考慮實現runnable介面這種。
我們要開啟乙個執行緒,那麼必須先給他乙個入口即run()方法,run()方法裡可以寫業務處理方法,這樣乙個執行緒就能流通並處理業務了。具體**如下:
/*** 所有執行緒任務介面
* 其他執行緒任務必須繼承該類
** @author hadestage
*/public abstract class task implements runnable catch (exception e)
}/**
* 所有任務的核心業務邏輯執行,哪個業務需要開啟多執行緒就繼承該類,然後重寫該方法的業務功能
** @throws exception
*/public abstract task taskcore() throws exception;
/*** 是否需要立即執行
*/protected abstract boolean needexecuteimmediate();
}這個執行緒任務類是我們業務功能啟用多執行緒時可繼承的介面,繼承時只需重寫業務方法
taskcore()即可。
作為示例demo,我建立了乙個檔案複製的執行緒任務,具體**如下:
/*** 建立檔案執行緒任務
* * @author hadestage
*/public class filecreatortask extends task
/*** 執行建立任務動作
*/@override
public task taskcore() catch (ioexception e)
return null;
}/**
* 是否需要立即執行
** @return false
*/@override
protected boolean needexecuteimmediate()
}其中fileutil.copyfile(new file(sourcefilename), new file(targefilename));
就是我們的關鍵業務**,複製檔案。
有時候,我們複製檔案、上傳檔案、傳送郵件等不僅僅只有乙個任務,很有可能多個複製、上傳、傳送任務同時進行,這時我們開啟乙個執行緒好像有些不夠用了,總不能乙個乙個的執行緒新建吧。那麼我們就需要同時開啟多個執行緒了,這就涉及到執行緒池的概念了,就像資料庫連線池那樣,建乙個執行緒池,裡面設定執行緒數,這樣就能解決多執行緒任務了。
/*** 執行緒池
* 建立執行緒池,銷毀執行緒池,新增新任務
** @author hadestage
*/public final class threadpool
建立單例執行緒池,從而保證執行緒池只有乙個且外部無法建立新的執行緒池,設定池中預設執行緒數,但支援手動設定執行緒數,poolworker是當前類的內部類,它充當執行緒池裡的執行緒,下文會有介紹。
接下來就是在threadpool這個執行緒池類中新增方法,使它能在建立執行緒池時設定執行緒數。
// 預設執行緒5個
private threadpool()
}private threadpool(int pool_worker_num)
}// 建立預設執行緒數
public static synchronized threadpool getinstance()
// 建立規定的執行緒個數
public static synchronized threadpool getinstance(int threadnumber)
建立完執行緒池,開啟了需要的執行緒,就得提供能往執行緒池裡增加任務並執行任務的方法。
/*** 增加新的任務
* 每增加乙個新任務,都要喚醒任務佇列
* @param newtask
*/public void addtask(task newtask)
}/**
* 批量增加新任務
* @param taskes
*/public void batchaddtask(listtaskes)
taskqueue.add(taskes.get(i));
}/* 喚醒佇列, 開始執行 */
taskqueue.notifyall();
}for (int i = 0; i < taskes.size(); i++) }}
任務執行完成後,我們還需要做一項工作,總不能讓執行緒池裡的執行緒一直佔著坑不放吧,你用完了,別人還等著用呢,所以我們還得銷毀執行緒池,等要用了再呼叫就行了。
/*** 銷毀執行緒池
*/public synchronized void destroy()
taskqueue.clear();
}執行緒池threadpool類中的內部類,該類的作用是具體化執行緒池,乙個任務是否執行,何時執行,怎麼執行都是由這裡面進行統一調配的。
class poolworker extends thread
public void setisrunning(boolean isrunning)
public void stopworker()
public boolean iswaiting()
/*** 迴圈執行任務
* 這也許是執行緒池的關鍵所在
*/public void run() catch (interruptedexception ie)
}/* 取出任務執行 */
r = (task) taskqueue.remove(0);
}if (r != null) else
} catch (exception e)
iswaiting = true;
r = null;}}
}}以上就是對執行緒池的建立和應用。現在有了業務功能,有了任務,也有了建立執行緒池和執行緒的方法,接下來就可以測試下了,可以新建乙個帶有main()函式的類,在main()方法裡建立執行緒池,然後新增任務即可了。具體**如下:
public static void main(string args)
多執行緒程式設計 執行緒的建立和終止
1 引言 linux 系統下的多執行緒遵循posix 執行緒介面,稱為pthread 編寫linux 下的多執行緒程式,需要使用標頭檔案pthread.h 連線時需要使用庫libpthread.a 順便說一下,linux 下pthread 的實現是通過系統呼叫clone 來實現的。clone 是li...
多執行緒程式設計 執行緒的建立和終止
1 引言 linux系統下的多執行緒遵循posix執行緒介面,稱為pthread。編寫linux下的多執行緒程式,需要使用標頭檔案pthread.h,連線時需要使用庫libpthread.a。順便說一下,linux下pthread的實現是通過系統呼叫clone 來實現的。clone 是linux所特...
多執行緒程式設計 執行緒的建立和終止
1 引言 linux系統下的多執行緒遵循posix執行緒介面,稱為pthread。編寫linux下的多執行緒程式,需要使用標頭檔案pthread.h,連線時需要使用庫libpthread.a。順便說一下,linux下pthread的實現是通過系統呼叫clone 來實現的。clone 是linux所特...