進程: 操作系統運行程序時分配資源的最小單位,進程和進程之間是相互獨立的
線程: cpu調度的最小單位,它必須依賴於進程.線程在運行時會佔用該進程的部分資源,線程之間是可以共享該進程所擁有的全部資源.但是線程與線程之間也有自己的獨立空間,稱之爲線程私有空間.
講到線程,一個進程有多個線程,所以會有多線程併發問題出現.
什麼是併發: 併發就好比一條高速收費口(這就相當於一個進程),假如這個入口有8個收費口,就代表着這個進程開了8個線程一直在跑. 這時併發好比在一個小時一共有多少汽車通過了這個收費口.這就是併發量, 這個併發控制不好就會出現排長隊現象,也就是影響性能.
在操作多線程中需要考慮以下事項
1:線程和線程之間的安全性
因爲一個進程中多線程是資源共享的,也就是都可以訪問同一內存地址當中的一個變量.
若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的.
若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則就可能影響線程安全.
2:線程之間的死循環過程
在解決1中線程安全性問題,會引入java的鎖機制,如果一旦產生死鎖,這時就會發生不可想象的事情.
假如有三個線程,主線程main,和二個子線程A B; 還有二個鎖lock1, lock2
二個子線程在跑的時候,假如線程A在執行的時候需要獲取鎖lock1, 在執行代碼時又需要獲取鎖lock2,
線程B它需要獲取鎖lock2,在執行代碼的時候又需要獲取鎖lock1.
而在多線程中就可能發生這樣的事情, 線程A一直在等鎖2釋放,而線程B一直在等鎖lock1釋放.這樣線程AB就會出現死鎖現象,而這時main線程需要lock1或者Lock2的話,這樣就一直獲取不了,這就主線程就會阻塞.
(3)線程太多了內存不足的情發生
因爲每創建一個線程,在運行這個線程的時候都會爲它分配一定資源,而且在創建的時候也是很耗性能的,所以在一直創建線程的時候就會導致性能很差,慎致內存不夠用的情況發生.在開發中一般操作線程都會用到線程池來處理.
線程的啓動
啓動線程有的方式
1: Thread thred = new Thread(); thread.start();
2: X implements Runnable; Thread thred = new Thread(new X()); thread.start();
3: MyCallable implements Callable ;使用Callable的時候又會涉及到FutureTask用法如下
FutureTask<String> future = new FutureTask<>(callable);
Thread thread = new Thread(future);
thread.start();
線程如何停止
首先開戶一個線程
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
thread.interrupt()使用線程的這個方法
public static class MyThread extends Thread {
@Override
public void run() {
super.run();
String name = Thread.currentThread().getName();
while (!isInterrupted()) {
System.out.println(name + " === is running");
}
}
}
然後執行thread.interrupt()就可以.
如果在while循環裏有sleep的話,就得多加一行代碼 ,如下
public static class MyThread extends Thread {
@Override
public void run() {
super.run();
String name = Thread.currentThread().getName();
while (!isInterrupted()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(name + " " + e.getMessage());
interrupt();
}
System.out.println(name + " === is running");
}
}
}
因爲sleep當發生異常的時候,會重置isInterrupt這個返回值
sleep wait yield的區別
sleep:
1讓該線程進入阻塞狀態,告訴系統在指定時間內不要調試該線程,它會讓出執行權給其它線程., 到時間後自動恢復,
2當線程處於上鎖的時候,這個方法不會釋放鎖,只會釋放CPU的調試權. 當時間到後,也不一定會立馬執行,什麼時候執行這個取決於系統的調試.
3:執行這個方法時必須捕獲異常,因爲當其它線程調用了這個線程的interrupt()方法時就會拋出InterruptedException這個異常.
wait:
1: 這個方法是Object裏的一個方法,執行它時會讓該線程進入阻塞狀態
2:當這個線程處於上鎖狀態時,它會釋放這個鎖以及讓出cpu的調度權,
3:和它搭配的方法有notify(),notifyAll().執行這二個方法就會讓等待的線程被激活,但也不是一定會立馬執行,得等cpu的調試,如果有鎖的話還得等獲取鎖才能繼續執行,
4:wait()方法,notify(),notiftAll()是用於協調多線程對共享數據的存取,所以只能在同步方法或者同步塊中使用,否則拋出IllegalMonitorStateException。
yield
1:該方法與sleep()類似,都是可以讓當前正在運行的線程暫停,
2:區別在於yield()方法不會阻塞該線程,它只是將線程轉換成就緒狀態,讓系統的調度器重新調度一次,並且yield()方法只能讓優先級相同或許更高的線程有執行的機會。