java线程概念_《Java基础知识》Java线程的概念
按照規劃,從本篇開始我們開啟『并發』系列內容的總結,從本篇的線程開始,到線程池,到幾種并發集合源碼的分析,我們一點點來,希望你也有耐心,因為并發這塊知識是你職業生涯始終繞不過的坎,任何一個項目都或多或少的要涉及一些并發的處理。
這一系列文章只能算是對并發這塊基本理論知識的一個總結與介紹,想要成為并發高手,必然是需要通過大規模并發訪問的線上場景應用,或許以后我有了相關經驗了,再給你們做一點分享吧。
基本的進程線程概念
進程和線程算是操作系統內兩個很基本、很重要的概念了,進程是操作系統中進行保護和資源分配的基本單位,操作系統分配資源以進程為基本單位。而線程是進程的組成部分,它代表了一條順序的執行流。
系統中的進程線程模型是這樣的:
進程從操作系統獲得基本的內存空間,所有的線程共享著進程的內存地址空間。當然,每個線程也會擁有自己私有的內存地址范圍,其他線程不能訪問。
由于所有的線程共享進程的內存地址空間,所以線程間的通信就容易的多,通過共享進程級全局變量即可實現。
同時,在沒有引入多線程概念之前,所謂的『并發』是發生在進程之間的,每一次的進程上下文切換都將導致系統調度算法的運行,以及各種 CPU 上下文的信息保存,非常耗時。而線程級并發沒有系統調度這一步驟,進程分配到 CPU 使用時間,并給其內部的各個線程使用。
在分時系統中,進程中的每個線程都擁有一個時間片,時間片結束時保存 CPU 及寄存器中的線程上下文并交出 CPU,完成一次線程間切換。當然,當進程的 CPU 時間使用結束時,所有的線程必然被阻塞。
JAVA 對線程概念的抽象
JAVA API 中用 Thread 這個類抽象化描述線程,線程有幾種狀態:
NEW:線程剛被創建
RUNNABLE:線程處于可執行狀態
BLOCKED、WAITING:線程被阻塞,具體區別后面說
TERMINATED:線程執行結束,被終止
其中 RUNNABLE 表示的是線程可執行,但不代表線程一定在獲取 CPU 執行中,可能由于時間片使用結束而等待系統的重新調度。BLOCKED、WAITING 都是由于線程執行過程中缺少某些條件而暫時阻塞,一旦它們等待的條件滿足時,它們將回到 RUNNABLE 狀態重新競爭 CPU。
此外,Thread 類中還有一些屬性用于描述一個線程對象:
private long tid:線程的序號
private volatile char name[]:線程的名稱
private int priority:線程的優先級
private boolean daemon = false:是否是守護線程
private Runnable target:該線程需要執行的方法
其中,tid 是一個自增的字段,每創建一個新線程,這個 id 都會自增一。優先級取值范圍,從一到十,數值越大,優先級越高,默認值為五。
線程案例:
packagedemo.knowledgepoints.scheduledtask.run;/***
* 線程類*/
public class ThreadTest implementsRunnable {public static int ticket = 9;
@Overridepublic voidrun() {try{
System.out.println("當前線程:"+Thread.currentThread().getName());while(true){synchronized (this) {
Thread.sleep(1000L);if (this.ticket > 0) {
ticket--;
System.out.println(Thread.currentThread().getName()+ ":出售一張票!");
System.out.println("剩余票量:" +ticket);
}else{
System.out.println("沒有票了!");
}
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
packagedemo.knowledgepoints.scheduledtask.run;public classThreadMemo {public static voidmain(String[] args) {
ThreadTest threadTest1=newThreadTest();newThread(threadTest1).start();newThread(threadTest1).start();
}
}
運行結果
從案例中我們可以知道:ThreadTest? 繼承了?Runnable 接口,并且實現了run方法。
在?ThreadMemo 中,我們創建ThreadTest,并且是執行了start() 方法,并沒有直接執行run方法。
從運行結果我們可以看出:我們運行了run方法里面的程序。
并且線程1和線程0 交替執行。
下面我們來看看這個線程的執行過程。
Runnable 是一個接口,它抽象化了一個線程的執行流,定義如下:
@FunctionalInterfacepublic interfaceRunnable {/*** When an object implementing interface Runnable is used
* to create a thread, starting the thread causes the object's
* run method to be called in that separately executing
* thread.
*
* The general contract of the method run is that it may
* take any action whatsoever.
*
*@seejava.lang.Thread#run()*/
public abstract voidrun();
}
第一步:實現接口Runnable接口。
第二步:創建一個線程,并且將實現Runnable接口的類放進去。
第三步:使用線程的start() 方法,啟動線程。這個時候,Jvm會自動去找到run方法,并且執行run方法,同時不影響主進程繼續往下執行。
線程案例:
public class Thread1 extendsThread {public static int ticket = 5;
@Overridepublic voidrun() {try{
System.out.println("當前線程:"+Thread.currentThread().getName());while(true){synchronized (this) {
Thread.sleep(2000L);if (this.ticket > 0) {
ticket--;
System.out.println(Thread.currentThread().getName()+ ":出售一張票!"+"剩余票量:" +ticket);
}else{
System.out.println("沒有票了!");
}
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
}
public classThreadTest1 {public static voidmain(String[] args) {
Thread thread= newThread1();
thread.start();
System.out.println("主線程!");
}
}
運行結果:
這是第二種線程實現方式:繼承?Thread 類。
看Thread 類:
class Thread implements Runnable
其實就是實現了Runnable 接口。
列舉一下:Thread 方法。
1、sleep
public static native void sleep(long millis)
這是一個本地方法,用于阻塞當前線程指定毫秒時長。
2、start
public synchronized void start()
這個方法可能很多人會疑惑,為什么我通過重寫 Runnable 的 run 方法指定了線程的工作,但卻是通過 start 方法來啟動線程的?
那是因為,啟動一個線程不僅僅是給定一個指令開始入口即可,操作系統還需要在進程的共享內存空間中劃分一部分作為線程的私有資源,創建程序計數器,棧等資源,最終才會去調用 run 方法。
3、interrupt
public void interrupt()
這個方法用于中斷當前線程,當然線程的不同狀態應對中斷的方式也是不同的,這一點我們后面再說。
4、join
public final synchronized void join(long millis)
這個方法一般在其他線程中進行調用,指明當前線程需要阻塞在當前位置,等待目標線程所有指令全部執行完畢。
線程案例:
public class ThreadDemo1 implements Callable{
@Overridepublic String call() throwsException {return "你好";
}public static void main(String[] args) throwsExecutionException, InterruptedException {
FutureTask futureTask= new FutureTask(newThreadDemo1()) ;newThread(futureTask).start();
System.out.println(futureTask.get());
}
}
運行結果:
總結
以上是生活随笔為你收集整理的java线程概念_《Java基础知识》Java线程的概念的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java求最大值_java-求一组整数中
- 下一篇: java调用方法返回数组_JAVA使用下