不忘初心 砥礪前行, Tomorrow Is Another Day !html
本文概要:java
概念:進程是程序的實體,是受操做系統管理的基本運行單元.編程
概念:操做系統中最小調度單元,一個進程能夠擁有多個線程.bash
線程的建立有3種方式.多線程
這種方式的本質也是實現Runnable接口.當咱們調用start方法時,並不會當即執行線程裏面代碼,而只是將線程狀態變爲可執行狀態,具體的執行時機由操做系統決定.併發
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("直接繼承Thread,重寫run方法");
}
public static void main(String[] args) {
new MyThread().start();
}
}
複製代碼
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("實現Runnable接口,重寫run方法");
}
public static void main(String[] args) {
new Thread(new MyRunnable()).start();
}
}
複製代碼
相比Runnable的三大功能.異步
關於ExecutorService與Future相關知識,將在線程池一篇文中詳細講解.這裏只須要知道Callable通常是和ExecutorService配合來使用的.ide
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("子線程正在幹活");
Thread.sleep(3000);
return "實現Callable接口,重寫Call方法";
}
public static void main(String[] args) throws Exception {
MyCallable myCallable = new MyCallable();
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(myCallable);
executorService.shutdown();
Thread.sleep(1000);//模擬正在幹活
System.out.println("主線程正在幹活");
//阻塞當前線程,等待返回結果.
System.out.println("等待返回結果:" + future.get());
System.out.println("主線程全部的活都幹完了");
}
}
//調用輸出
子線程正在幹活
主線程正在幹活
等待返回結果:實現Callable接口,重寫Call方法
主線程全部的活都幹完了
複製代碼
線程同步的目的就是爲了防止當多個線程對同一個數據對象進行存儲時,形成數據不一致的問題.函數
同步問題示例post
public class SyncThread extends Thread {
private static final String TAG = "SyncThread";
private Pay pay;
public SyncThread(String name, Pay pay) {
super(name);
this.pay = pay;
}
@Override
public void run() {
while (isRunning) {
pay.count();
}
}
}
Pay.java
/**
* 未同步時
*/
public void count() {
if (count > 0) {
System.out.println(Thread.currentThread().getName() + ":>" + count--);
} else {
isRunning = false;
}
}
複製代碼
//未使用同步時
D: 線程3:>912
D: 線程1:>911
D: 線程2:>911 //此時已經出現數據不同
D: 線程1:>909
D: 線程3:>910
D: 線程2:>908
D: 線程1:>907
D: 線程3:>906
D: 線程2:>905
D: 線程1:>904
D: 線程2:>903
D: 線程3:>903
D: 線程1:>902
D: 線程2:>901
D: 線程3:>900
//使用同步時
D: 線程1:>1000
D: 線程2:>999
D: 線程2:>998
D: 線程1:>997
D: 線程2:>996
D: 線程1:>995
D: 線程2:>994
D: 線程1:>993
D: 線程2:>992
D: 線程1:>991
D: 線程2:>990
D: 線程1:>989
D: 線程2:>988
D: 線程1:>987
D: 線程2:>986
D: 線程1:>985
D: 線程2:>984
D: 線程1:>983
複製代碼
爲了解決異步的問題,JAVA提供了鎖的機制,synchronized 關鍵字.能夠很方便的實現線程的同步.
先理解如何進行手動加鎖,這樣更容易理解自動加鎖的機制.
僞代碼
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition;
lock.lock();
try {
if(count == 0){
//進阻,放鎖
condition.await();
}
//喚醒所以條件,而阻塞的全部線程
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
複製代碼
資源互斥,線程數據同步,提供了自動加鎖.同步本質見java內存模型.
在實際開發中大多數狀況使用同步方法與同步代碼塊,實現同步,除非一些須要高度控制鎖的則使用重入鎖和條件對象.
線程同步的四種方式.
1. 同步方法
private synchronized void countSyncMethod() {
if (count > 0) {
Log.d(TAG, Thread.currentThread().getName() + ":>" + count--);
} else {
isRunning = false;
}
}
複製代碼
2. 同步代碼塊
private void countSyncCode() {
synchronized (this) {
if (count > 0) {
Log.d(TAG, Thread.currentThread().getName() + ":>" + count--);
} else {
isRunning = false;
}
}
}
複製代碼
3. 使用重入鎖
private void countSyncLock() {
mLock.lock();
try {
if (count > 0) {
Log.d(TAG, Thread.currentThread().getName() + ":>" + count--);
} else {
isRunning = false;
}
} catch (Exception e) {
e.printStackTrace();
}inally{
mLock.unlock();
}
}
複製代碼
4. 使用特殊域變量(volatile)
先了解java內存模型與「三性」知識.
java內存模型定義了線程和主內存之間的抽象關係.
線程在對變量進行存與取時,通常先改變工做內存的變量值,再在某個時機刷新到主存中去.這樣就會致使多線程併發時另外一個線程從主存中獲取到的不必定是最新的值.
這樣當一個共享變量被volatile修飾時.
private int x;
private int y;
//依賴自身
x++;
//依賴其餘變量
if(x > y){
x = y;
}
複製代碼
示例代碼
@Override
public void run() {
//中斷目標線程,並非指當即中止線程,而僅僅只是將線程的標識爲true,通常由目標線程本身去檢測並決定是否終止線程.
for (int j = 0; j <100000000 ; j++) {
if (Thread.currentThread().isInterrupted()){
System.out.println("Interrupted!已經中斷中止輸出.開始收尾工做1");
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//處於阻塞狀態的線程,也會立馬被中斷,因此就會拋出此異常.
System.out.println("Interrupted!已經中斷中止輸出.開始收尾工做2");
return;
}
System.out.println("還沒中斷繼續輸出j:" + j);
}
}
複製代碼
關於Thread基礎相關就介紹到這裏了.接着下一篇介紹多線程編程中的線程池.Demo源碼在最後一篇一塊兒給出.
因爲本人技術有限,若有錯誤的地方,麻煩你們給我提出來,本人不勝感激,你們一塊兒學習進步.
參考連接: