程序、進程和線程html
1、程序java
2、進程安全
進程是資源(CPU、內存等)分配的基本單位,它是程序執行時的一個實例,即運行中的程序。網絡
一個運行着的程序,可能有多個進程。進程在操做系統中執行特定的任務。多線程
程序運行時系統就會建立一個進程,併爲它分配資源,而後把該進程放入進程就緒隊列,進程調度器選中它的時候就會爲它分配CPU時間,程序開始真正運行。ide
3、 線程函數
線程是程序中執行的線程。Java虛擬機容許應用程序同時運行多個執行線程。測試
每一個線程都有優先權。 具備較高優先級的線程優先於具備較低優先級的線程執行。 每一個線程可能也可能不會被標記爲守護進程。 當在某個線程中運行的代碼建立一個新的
Thread
對象時,新線程的優先級最初設置爲等於建立線程的優先級,而且當且僅當建立線程是守護進程時纔是守護進程線程。this當Java虛擬機啓動時,一般會有一個非守護進程線程(一般調用某個指定類的名爲
main
的方法)。 Java虛擬機繼續執行線程,直到發生如下任一狀況:操作系統
- 已調用類
Runtime
的exit
方法,而且安全管理器已容許執行退出操做。- 經過調用
run
方法返回或拋出超出run
方法傳播的異常,全部非守護程序線程的線程都已死亡。
建立線程方式一:繼承Thread類,重寫run()方法,調用start()開啓線程
public class MyThread extends Thread{ @Override public void run() { //子線程方法 for (int i = 0; i < 20; i++) { System.out.println("我是子線程" + i); } } public static void main(String[] args) { //開啓子線程 new MyThread().start(); for (int i = 0; i < 20; i++) { System.out.println("我是主線程" + i); } } }
執行結果
能夠發現,主線程和子線程是」同時「進行的。
Thread類實現了Runnable接口,內部經過靜態代理調用了run()方法
public class MyThread implements Runnable{ @Override public void run() { //子線程方法 for (int i = 0; i < 20; i++) { System.out.println("我是子線程" + i); } } public static void main(String[] args) { //建立線程對象,代理線程 new Thread(new MyThread()).start(); for (int i = 0; i < 20; i++) { System.out.println("我是主線程" + i); } } }
使用方法基本和繼承Thread類相同,執行結果也類似。
示例代碼
public class MyThread implements Callable<Boolean> { @Override public Boolean call() { //子線程方法 System.out.println("執行了子線程"); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread t1 = new MyThread(); //建立執行服務 ExecutorService ser = Executors.newFixedThreadPool(1); //提交執行 Future<Boolean> result1 = ser.submit(t1); //獲取結果 boolean r1 = result1.get(); //關閉服務 ser. shutdownNow(); } }
建立狀態:
Thread t = new Thread()
線程對象一旦建立就進入到了新生狀態。
就緒狀態:
當調用start()方法,線程當即進入就緒狀態,但不意味着當即調度執行。
運行狀態:
進入運行狀態,線程才真正執行線程體的代碼塊。
阻塞狀態:
當調用sleep, wait 或同步鎖定時,線程進入阻塞狀態,就是代碼不往下執行,阻塞事件解除後,從新進入就緒狀態,等待cpu調度執行。
不必定每一個線程都會進入阻塞狀態
死亡狀態:
線程中斷或者結束,一旦進入死亡狀態,就不能再次啓動。
方法 | 說明 |
---|---|
setPriority(int newPriority) | 更改線程的優先級 |
static void sleep(long millis) | 在指定的毫秒數內讓當前正在執行的線程休眠 |
void join() | 等待該線程終止 |
static void yield() | 暫停當前正在執行的線程對象,並執行其餘線程 |
void interrupt() | 中斷線程,別用這個方式 |
boolean isAlive() | 測試線程是否處於活動狀態 |
使用標誌位的例子
public class MyThread implements Runnable{ private boolean flag = true; @Override public void run() { //子線程方法 int i = 0; while (flag) { System.out.println("我是子線程" + i++); } } public void stop() { this.flag = false; } public static void main(String[] args) { MyThread thread = new MyThread(); new Thread(thread).start(); for (int i = 0; i < 1000; i++) { System.out.println("主線程" + i); if (i == 800) { thread.stop(); System.out.println("線程中止了"); } } } }
結果如圖
線程休眠的例子:
public class MyThread{ public static void main(String[] args) throws InterruptedException { while (true) { Date date = new Date(System.currentTimeMillis()); System.out.println(new SimpleDateFormat("HH:mm:ss").format(date)); Thread.sleep(1000); } } }
每一秒輸出當前時間,使用sleep(1000)來使得每次執行完休眠一秒。
示例
public class MyThread{ public static void main(String[] args) { Runnable runnable = () -> { System.out.println(Thread.currentThread().getName() + "線程開始"); Thread.yield(); //線程禮讓 System.out.println(Thread.currentThread().getName() + "線程結束"); }; new Thread(runnable, "a").start(); new Thread(runnable, "b").start(); new Thread(runnable, "c").start(); } }
執行結果
能夠發現每次的結果都不相同
能夠想象成一個VIP線程,強制插隊,查到當前線程,直到本身執行完畢。很是霸道
會使得線程阻塞。
public class MyThread{ public static void main(String[] args) throws InterruptedException { Runnable runnable = () -> { for (int i = 0; i < 10; i++) { System.out.println("VIP線程來了" + i); } }; Thread thread = new Thread(runnable); thread.start(); for (int i = 0; i < 50; i++) { if (i == 30) thread.join(); System.out.println("主線程" + i); } } }
結果如圖
線程狀態。線程能夠處於如下狀態之一:
線程在給定時間點只能處於一種狀態。 這些狀態是虛擬機狀態,不反映任何操做系統線程狀態。
經過如下代碼演示線程狀態的監聽
public class MyThread{ public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(()->{ for (int i = 0; i < 5; i++) { try { Thread.sleep(500); } catch (InterruptedException ignored) {} } }); System.out.println(thread.getState()); thread.start(); while (thread.getState() != Thread.State.TERMINATED) { Thread.sleep(500); System.out.println(thread.getState()); } } }
運行結果
Java提供一個線程調度器來監控程序中啓動後進入就緒狀態的全部線程, 線程調度
器按照優先級決定應該調度哪一個線程來執行。
觀察Thread類源代碼,能夠看到優先級在jdk中的定義
/** * The minimum priority that a thread can have. */ public static final int MIN_PRIORITY = 1; /** * The default priority that is assigned to a thread. */ public static final int NORM_PRIORITY = 5; /** * The maximum priority that a thread can have. */ public static final int MAX_PRIORITY = 10;
咱們能夠經過
System.out.println(Thread.currentThread().getPriority());
來輸出當前線程的優先級,能夠獲得默認優先級是5。
可使用如下方式改變或獲取優先級
getPriority() //獲得優先級 setPriority(int xxx) 設置優先級
若是設置的優先級超出限制,則會拋出一個IllegalArgumentException異常:
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); }
優先級低只是意味着得到調度的機率低,並非優先級低就不會被調用了,這都是看CPU的調度。
最好在start前設置優先級
所謂守護線程,是指在程序運行的時候在後臺提供一種通用服務的線程,好比垃圾回收線程就是一個很稱職的守護者,而且這種線程並不屬於程序中不可或缺的部分。所以,當全部的非守護線程結束時,程序也就終止了,同時會殺死進程中的全部守護線程。反過來講,只要任何非守護線程還在運行,程序就不會終止。
用戶線程和守護線程二者幾乎沒有區別,惟一的不一樣之處就在於虛擬機的離開:若是用戶線程已經所有退出運行了,只剩下守護線程存在了,虛擬機也就退出了。 由於沒有了被守護者,守護線程也就沒有工做可作了,也就沒有繼續運行程序的必要了。
演示,先定義兩個線程,一個守護線程,一個普通線程
Thread daemon = new Thread(()->{ while (true) { System.out.println("守護線程..."); } }); Thread normal = new Thread(()->{ for (int i = 0; i < 10; i++) { System.out.println("子線程..."); } System.out.println("子線程結束"); });
而後設置守護線程
daemon.setDaemon(true);
啓動兩個線程後,能夠看到,守護線程並無結束就中止了程序。