我在寫「系統間通訊技術專欄」的時候,收到不少讀者的反饋。其中有一部分讀者但願我抽空寫一寫本身關於對JAVA線程的使用經驗和總結。巧的是,這個月我所在的技術團隊也有不少同事跟我討論關於JAVA中線程的操做。正好本月我工做也不是很忙,除了繼續推動個人重點專欄「系統間通訊技術」外,能夠更多的空餘時間跟各位讀者分享本身對JAVA線程技術的理解和使用經驗。html
本人不才,應讀者要求新開專欄,與各位讀者分享本身對JAVA線程技術的理解和使用經驗。這個專欄將分紅兩個部分:線程基礎知識和鎖知識。專欄的難度應該是我所開專欄中難度最低的一個,着重於線程基礎知識的講解,更適合JAVA初學者閱讀,目的是但願可以幫助你們提升codeing水平和程序質量。若是您是經驗老道的高手也歡迎和本人討論相關問題,對本人文章的論點進行勘誤,您的支持是我寫做的關鍵動力。固然本人的更多精力仍是放在繼續完成「系統間通訊技術」這個專欄。(本系列的博客文章將不會置頂)java
線程是一個操做系統級別的概念。JAVA語言(包括其餘編程語言)自己不建立線程;而是調用操做系統層提供的接口建立、控制、銷燬線程實例。web
首先要說明的是,根據操做系統的不一樣(Windows/Unix/Linux/其餘),他們所支持的線程底層實現和操做效果也是不盡相同的。不過一個操做系統支持的線程至少會有四種狀態:就緒、執行、阻塞和終結。線程在四種狀態下進行切換,都是要消耗很多的CPU計算能力的。apache
而且根據操做系統使用線程的進程的不同,線程還分爲用戶線程和操做系統線程。操做系統線程(內核線程),是指操做系統內核爲了完成硬件接口層操做,由操做系統內核建立的線程:例如I/O操做的內核線程,這些線程應用程序是不能干預的;用戶線程,是指用戶安裝/管理的應用程序,爲執行某一種操做,而由這個應用程序建立的線程。後文咱們討論的JAVA線程,都是用戶級線程。編程
線程在建立時,操做系統不會爲這個線程分配獨立的資源(除了必要的數據支撐)。一個應用程序(進程)下的全部線程,都是共享這個應用程序(進程)中的資源,例如這個應用程序的CPU資源、I/O資源、內存資源。多線程
如今基本上主流操做系統都支持多線程實現。即一個應用程序中(一個進程中),能夠建立多個線程。一個應用程序下,各個線程間均可以進行通信、能夠進行狀態互操做。且一個進程中,至少有一個線程存在。編程語言
JAVA中提供了豐富的操做系統接口實現,幫助咱們進行線程操做。這些實現分佈在java的java.lang基礎包、java.io基礎包和java.util.concurrent工具包當中;這個專欄所涉及到的代碼示例也會從易到難向你們進行演示。咱們先來看看JAVA中最基本的線程操做實現(高手請繞行)。ide
java.lang.Thread類是JAVA中用於實現線程操做的最基本的類之一。您能夠建立一個集成Thread類的子類來定義您本身的線程實現:svg
package test.thread.base;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.BasicConfigurator;
public class MyDefindThread extends Thread {
static {
BasicConfigurator.configure();
}
/** * 日誌。必定要使用Log4j才行。不然你就用System.out吧 */
private static final Log LOGGER= LogFactory.getLog(MyDefindThread.class);
/* (non-Javadoc) * @see java.lang.Thread#run() */
@Override
public void run() {
Long threadId = this.getId();
MyDefindThread.LOGGER.info("線程(" + threadId + ")作了一些事情,而後結束了。");
}
public static void main(String[] args) throws Exception {
new MyDefindThread().start();
}
}
除了能夠繼承java.lang.Thread類來定義本身的線程外,您還能夠實現java.lang.Runnable接口來定義一個線程(通常狀況,咱們優先使用這種方式):工具
package test.thread.base;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.BasicConfigurator;
public class MyDefindRunnable implements Runnable {
static {
BasicConfigurator.configure();
}
/** * 日誌。必定要使用Log4j才行。不然你就用System.out吧 */
private static final Log LOGGER= LogFactory.getLog(MyDefindThread.class);
/* (non-Javadoc) * @see java.lang.Runnable#run() */
@Override
public void run() {
// 獲取當前線程的ID
long threadId = Thread.currentThread().getId();
MyDefindRunnable.LOGGER.info("線程(" + threadId + ")作了一些事情,而後結束了。");
}
public static void main(String[] args) throws Exception {
new Thread(new MyDefindRunnable()).start();
}
}
以上的兩段代碼都沒有太多可講解的。您能夠在調試環境下觀察到JAVA應用程序是如何運行線程的:
下一篇文章中,咱們將繼續介紹Java所支持的線程間基本互操做,包括:阻塞、喚醒、終止等操做;而後介紹Java原生線程池的工做原理和基本操做。