- 線程運行速度比進程速度快
實現多線程的3種方案
可以實現Thread類
-
任何情況下,只要定義了多線程,多線程的啓動永遠只有一種方案,Thread類中的start()方法
-
內部調用的是strat0(),這是一個JNI實現方法,JVM根據不同的系統實現不同的start0()方法
import java.util.function.*; class MyThread extends Thread{ private String title; public MyThread(String title){ this.title = title; } @Override public void run(){ for(int i= 0;i< 10;i++){ System.out.println(this.title + "i = " + i); } } } public class JavaDemo{ public static void main(String[] arges){ MyThread myThread01 = new MyThread("TEST01 "); myThread01.start(); MyThread myThread02 = new MyThread("TEST02 "); myThread02.start(); MyThread myThread03 = new MyThread("TEST03 "); myThread03.start(); } }
Runnable實現多線程
-
1.8之後就變爲函數式接口,可以直接實現lambda函數式
-
開發中首要考慮Runnable實現,並通過Thread.start()方法
-
藉助構造方法:public Thread(Runnable target)實現
- 這裏是實現接口,所以MyThread可以作爲一個正常的類,去繼承其他類或是實現多個接口
import java.util.function.*;
class MyThread implements Runnable{
private String title;
public MyThread(String title){
this.title = title;
}
@Override
public void run(){
for(int i= 0;i< 10;i++){
System.out.println(this.title + "i = " + i);
}
}
}
public class JavaDemo{
public static void main(String[] arges){
Thread thread = new Thread(new MyThread("TEST"));
thread.start();
}
}
-
Lambda函數式(超簡潔)
public class JavaDemo{ public static void main(String[] arges){ Runnable run = ()->{ System.out.println("這裏在多線程中執行"); }; new Thread(run).start(); } }
#更簡單的
import java.util.function.*;
public class JavaDemo{
public static void main(String[] arges){
new Thread(()->{
System.out.println("dsfsdf");
}).start();
}
}
Thread與Runnable的關係
- ````public class Thread extends Object implements Runnable{}```Thread類也是實現了Runnable接口的子類
- 有上面瞭解到,多線程的方法主要都是由Thread實現的,所以操作系統的資源調用也是通過Thread調用的
- Thread爲代理類,MyThread或者實現Runnable接口的類爲真實類
- 多線程開發的本質是在於多個線程可以進行對統一資源的搶佔
Callable實現多線程
-
Runnable的缺點是,執行完畢後,無法給主線程一個返回值
-
1.5之後實現的新方法
java.util.concurrent.Callable
接口,使用泛型返回數據 -
方法流程圖
Runnable與Callable
-
Runnable是在JDK1.0的時候提出的多線程的實現接口,而Callable是JDK1.5之後提出來的
-
java.lang.Runnable接口之中只提出一個run()方法,並沒有返回值
-
java.util.concurrent.Callable接口提供有call()方法,可以有返回值;
import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; class MyThread implements Callable<String>{ @Override public String call() throws Exception{ for(int i=0;i < 1000;i++){ System.out.println("==========" + i); } return "=====end========"; } } public class JavaDemo{ public static void main(String[] arges)throws Exception{ FutureTask<String> task = new FutureTask<>(new MyThread()); new Thread(task).start(); System.out.println(task.get()); } }
其他小知識
多線程的狀態
狀態
- 創建
- start()
- 就緒狀態
- 阻塞狀態
- 運行狀態
- 就緒狀態
- 終止
進程與休眠
- 一個程序中可以啓動若干個JVM,每個JVM就是一個進程
- 休眠可以設置爲毫秒和納秒2中精確度,如果被打斷會拋出Exception子類的異常,必須處理
- 所有線程運行同一個方法時,也會有先後,並沒有絕對的一起執行
線程的名稱
-
開發爲了獲得一些線程的操作,可以通過線程的名稱獲得
- 構造方法:public Thread(Runnable target,String name)
- 設置名稱:public final void setName(String name)
- 取的名稱:public final String getName();
- 獲得當前線程的方法:Thread.currentThread().getName()
線程中斷
- 判斷是否被中斷:public boolean isInterrupted();//被中斷 返回true
- 中斷線程執行:public void interrupt();
線程的強制執行
public class test {
public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
Thread thread = new Thread(()->{
for (int x = 0; x < 100; x++){
if (x == 3){
try {
mainThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("thread == " + x);
}
});
thread.start();
for (int i = 0; i < 100; i++){
System.out.println("霸道主線程mainThread == " + i);
}
}
}
線程的禮讓
-
禮讓:public void yield()
-
每次出現競爭的時候,都會禮讓一次,大部分時候會禮讓,但是不明顯
public static void main(String[] args) { Thread thread = new Thread(()->{ for (int x = 0; x < 100; x++){ if (x % 3 == 0){ Thread.yield(); System.out.println("===========我禮讓一次==========="); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("thread == " + x); } }); thread.start(); for (int x = 0; x < 100; x++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("霸道主線程mainThread == " + x); } }
優先級設置
- 設置優先級:public final void setPriority(int new Priority);
- 默認優先級: 5(NORM_PRIORITY)
- 最高優先級:MAX_PRIORITY 10
- 中等優先級:NORM_PRIORITY 5
- 最低優先級:MIN_PRIORITY 1
- 獲取優先級:public final int getPriority()
同步方法
同步代碼塊、同步方法
- 同步代碼塊,速度會變慢
線程的等待機制
- 死等:wait()
- 設定等待時間 wait(long timeout,int nanos)
- 喚醒第一個等待線程:notify()
- 喚醒全部線程:notifyALL()
- 禁用的方法:stop()、suspend()掛起、destroy()銷燬
- 用全局變量去停止線程
守護線程
- 設置守護線程:public final void setDaemon(boolean on);
- 判斷是否爲守護線程:public final boolean isDaemon();
- 設置爲守護線程後,整體程序結束後,守護線程也將結束
- JVM最大的守護線程就是GC線程,程序結束,GC也一起結束
volatile
正常的變量處理步驟:
- 獲取變量原有的數據內容副本
- 利用副本爲變量進行數學計算
- 將計算後的變量,保存到原始空間之中
volatile關鍵字
- 表示不使用副本,而是直接操作變量,所以並不是同步操作,也需要同步關鍵字
volatile與syncharoniaed的區別
- volaile主要在屬性上使用,而synchronized是在代碼塊與方法上使用的
- volatile無法描述同步的處理,它只是一種直接內存的處理,避免的副本的操作,而synchronized是實現同步的
- volatile配送syncharoniaed處理同步,可以更快的運行
StringBuffer
-
線程安全的字符串添加方法,1.0之後提供的
-
追加:new StringBUffer(“www.cn”).insert(4,“mldn”)在第4個開始追加
-
部分刪除:buf.append(“www.mldn.com”).delete(4,8).insert(4,“bridge”);//“www.bridge.com”
-
支付反轉:buf.reverse()
-
StringBuilder:非線程安全的效率更高,1.5之後才提供的