進程:進程指正在運行的程序骗露。確切的來說岭佳,當一個程序進入內(nèi)存運行,即變成一個進程萧锉,進程是處于運行過程中的程序珊随,并且具有一定獨立功能。
線程:線程是進程中的一個執(zhí)行單元驹暑,負責當前進程中程序的執(zhí)行玫恳,一個進程中至少有一個線程。一個進程中是可以有多個線程的优俘,這個應用程序也可以稱之為多線程程序京办。
簡而言之:一個程序運行后至少有一個進程,一個進程中可以包含多個線程
什么是多線程呢帆焕?即就是一個程序中有多個線程在同時執(zhí)行惭婿。
通過下圖來區(qū)別單線程程序與多線程程序的不同:
? 單線程程序:即,若有多個任務只能依次執(zhí)行叶雹。當上一個任務執(zhí)行結束后财饥,下一個任務開始執(zhí)行。如折晦,去網(wǎng)吧上網(wǎng)钥星,網(wǎng)吧只能讓一個人上網(wǎng),當這個人下機后满着,下一個人才能上網(wǎng)谦炒。
? 多線程程序:即贯莺,若有多個任務可以同時執(zhí)行。如宁改,去網(wǎng)吧上網(wǎng)缕探,網(wǎng)吧能夠讓多個人同時上網(wǎng)。
以下舉幾個模型圖
程序在電腦中運行原理
? 分時調(diào)度
所有線程輪流使用 CPU 的使用權还蹲,平均分配每個線程占用 CPU 的時間爹耗。
? 搶占式調(diào)度
優(yōu)先讓優(yōu)先級高的線程使用 CPU,如果線程的優(yōu)先級相同谜喊,那么會隨機選擇一個(線程隨機性)潭兽,Java使用的為搶占式調(diào)度。
實際上锅论,CPU(中央處理器)使用搶占式調(diào)度模式在多個線程間進行著高速的切換讼溺。對于CPU的一個核而言楣号,某個時刻最易,只能執(zhí)行一個線程,而 CPU的在多個線程間切換速度相對我們的感覺要快炫狱,看上去就是在同一時刻運行藻懒。
其實,多線程程序并不能提高程序的運行速度视译,但能夠提高程序運行效率嬉荆,讓CPU的使用率更高。
主線程
:jvm啟動后酷含,必然有一個執(zhí)行路徑(線程)從main方法開始的鄙早,一直執(zhí)行到main方法結束,這個線程在java中稱之為主線程椅亚。當程序的主線程執(zhí)行時限番,如果遇到了循環(huán)而導致程序在指定位置停留時間過長,則無法馬上執(zhí)行下面的程序呀舔,需要等待循環(huán)結束后能夠執(zhí)行弥虐。
那么,能否實現(xiàn)一個主線程負責執(zhí)行其中一個循環(huán)媚赖,再由另一個線程負責其他代碼的執(zhí)行霜瘪,最終實現(xiàn)多部分代碼同時執(zhí)行的效果?
能夠實現(xiàn)同時執(zhí)行惧磺,通過Java中的多線程技術來解決該問題颖对。
Thread類
Java虛擬機允許應用程序同時執(zhí)行多個執(zhí)行線程。 每個線程都有優(yōu)先權磨隘。 具有較高優(yōu)先級的線程優(yōu)先于優(yōu)先級較低的線程執(zhí)行缤底。 每個線程可能也可能不會被標記為守護程序布讹。 當在某個線程中運行的代碼創(chuàng)建一個新的Thread對象時,新線程的優(yōu)先級最初設置為等于創(chuàng)建線程的優(yōu)先級训堆,并且當且僅當創(chuàng)建線程是守護進程時才是守護線程描验。
當Java虛擬機啟動時,通常有一個非守護進程線程(通常調(diào)用某些指定類的名為main的方法)坑鱼。 Java虛擬機將繼續(xù)執(zhí)行線程膘流,直到發(fā)生以下任一情況:
已經(jīng)調(diào)用了Runtime類的exit方法,并且安全管理器已經(jīng)允許進行退出操作鲁沥。
所有不是守護進程線程的線程都已經(jīng)死亡呼股,無論是從調(diào)用返回到run方法還是拋出超出run方法的run 。
創(chuàng)建一個新的執(zhí)行線程有兩種方法画恰。 一個是將一個類聲明為Thread的子類彭谁。 這個子類應該重寫run類的方法Thread 。 然后可以分配并啟動子類的實例允扇。 例如缠局,計算大于規(guī)定值的素數(shù)的線程可以寫成如下:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
System.out.println("我是一個新線程");
}
}
然后,以下代碼將創(chuàng)建一個線程并啟動它運行:
PrimeThread p = new PrimeThread(143);
p.start();
Thread類的方法摘要
思考:線程對象調(diào)用 run方法和調(diào)用start方法區(qū)別考润?
線程對象調(diào)用run方法不開啟線程狭园。僅是對象調(diào)用方法。線程對象調(diào)用start開啟線程糊治,并讓jvm調(diào)用run方法在開啟的線程中執(zhí)行唱矛。
創(chuàng)建線程的目的是什么?
是為了建立程序單獨的執(zhí)行路徑井辜,讓多部分代碼實現(xiàn)同時執(zhí)行绎谦。也就是說線程創(chuàng)建并執(zhí)行需要給定線程要執(zhí)行的任務。
對于之前所講的主線程粥脚,它的任務定義在main函數(shù)中窃肠。自定義線程需要執(zhí)行的任務都定義在run方法中。
Thread類run方法中的任務并不是我們所需要的阿逃,只有重寫這個run方法铭拧。既然Thread類已經(jīng)定義了線程任務的編寫位置(run方法),那么只要在編寫位置(run方法)中定義任務代碼即可恃锉。所以進行了重寫run方法動作搀菩。
package cn.itcast.demo;
/*
* 創(chuàng)建和啟動一個線程
* 創(chuàng)建Thread子類對象
* 子類調(diào)用方法start();注意:不能調(diào)用子類run()方法,
* 子類調(diào)用run()方法并不開啟線程,只能調(diào)用start方法開啟線程,
* jvm會調(diào)用run方法在開啟的線程中執(zhí)行
*
* 讓線程程序執(zhí)行 虛擬機調(diào)用線程中的run
*
*/
public class ThreadDemo {
public static void main(String[] args) {
SubThread st = new SubThread();
st.start();
for(int i = 0;i<50;i++)
{
System.out.println("Main......"+i);
}
}
}
package cn.itcast.demo;
/*
* 定義子類 繼承Thread
* 重寫方法run
*/
public class SubThread extends Thread {
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("run...."+i);
}
}
}
獲取線程的名字
Thread類提供一個getName()用于返回線程的名字,currentThread(),返回主線程的名字
package cn.itcast.demo1;
import java.util.TreeSet;
public class NameThread extends Thread{
@Override
public void run() {
System.out.println(super.getName());
}
}
package cn.itcast.demo1;
/*
* JVM開啟主線程,運行方法main,主線程也是線程,是線程就必然是Thread類的對象
* Thread類中,靜態(tài)方法
* static Thread currentThread()返回正在執(zhí)行的線程對象
*/
public class ThreadDemo {
public static void main(String[] args) {
NameThread t = new NameThread();
t.start();
Thread t2 = Thread.currentThread();
System.out.println(t2.getName());
}
}