《永劫無間》鋼鐵俠MK3捏臉資料分享
阿新 • • 發佈:2021-08-19
Java多執行緒基礎(1)
學習筆記為手打,教程為 【狂神說Java】多執行緒詳解
執行緒基礎
1. 執行緒就是獨立執行路徑
2. 在程式執行時,及時沒有自己建立執行緒,後臺夜會有多個執行緒,如主執行緒,gc執行緒
3. main()稱之為主執行緒,為系統的入口,用於執行整個程式
4. 在一個程序中,如果開闢多個執行緒,執行緒的運作有排程器安排排程,排程器是與作業系統緊密相關的,先後順序是不能人為的干預的
5. 對同一份資源操作時,會存在資源搶奪問題,需要加入併發控制
6. 執行緒會帶來額外的開銷,如cpu排程時間,併發控制開銷
7. 每個執行緒在自己的工作記憶體互動,記憶體控制不當會造成資料的不一致
執行緒建立
三種建立方式
Thread class
子類繼承Thread具備多執行緒功能
啟動執行緒:子類物件.start()
OOP單繼承侷限性
public class ThreadsDemo2 extends Thread{ private String url; /*網路圖片位置*/ private String name; /*檔名稱*/ public ThreadsDemo2(String url, String name) { this.url = url; this.name = name; } //下載圖片的執行體 @Override public void run() { WebDownloader webDownloader = new WebDownloader(); try { webDownloader.downloader(url,name); System.out.println("下載圖片為"+ name); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { String url1 = "https://img0.baidu.com/it/u=4156074303,275806129&fm=26&fmt=auto&gp=0.jpg"; String url2 = "https://img1.baidu.com/it/u=1684000154,1654099979&fm=26&fmt=auto&gp=0.jpg"; String url3 = "https://img0.baidu.com/it/u=1506294494,3075748085&fm=26&fmt=auto&gp=0.jpg"; String name1 = "頭像1.jpg"; String name2 = "頭像2.jpg"; String name3 = "頭像3.jpg"; ThreadsDemo2 t1= new ThreadsDemo2(url1,name1); ThreadsDemo2 t2= new ThreadsDemo2(url1,name2); ThreadsDemo2 t3= new ThreadsDemo2(url1,name3); t1.start(); t2.start(); t3.start(); } } /** * 下載器 */ class WebDownloader { public void downloader(String url, String name) throws IOException { FileUtils.copyURLToFile(new URL(url), new File(name)); } }
第一次執行
第二次執行
結論:兩次執行的次序並不按順序,可知三個執行緒是並行的。
Runnable interface
實現Runnable具有多執行緒能力
啟動執行緒:傳入目標物件+thread物件.start()
靈活,方便物件被多個執行緒使用
public class ThreadsDemo3 implements Runnable{ @Override public void run() { //run()方法執行緒體 for (int i = 0; i < 200; i++) { System.out.println("========run"+i); } } public static void main(String[] args) { ThreadsDemo3 t1 = new ThreadsDemo3(); new Thread(t1).start(); for (int i = 0; i < 2000; i++) { System.out.println("======main"+i); } } }
Callable interface (暫時瞭解 21/08/23)
public class ThreadsDemo6 implements Callable<Boolean> {
private String url; /*網路圖片位置*/
private String name; /*檔名稱*/
public ThreadsDemo6(String url1, String name1) {
this.url = url1;
this.name = name1;
}
@Override
public Boolean call() throws Exception {
WebDownloader webDownloader = new WebDownloader();
try {
webDownloader.downloader(url,name);
System.out.println("下載圖片為"+ name);
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
String url1 = "https://img0.baidu.com/it/u=4156074303,275806129&fm=26&fmt=auto&gp=0.jpg";
String url2 = "https://img1.baidu.com/it/u=1684000154,1654099979&fm=26&fmt=auto&gp=0.jpg";
String url3 = "https://img0.baidu.com/it/u=1506294494,3075748085&fm=26&fmt=auto&gp=0.jpg";
String name1 = "頭像1.jpg";
String name2 = "頭像2.jpg";
String name3 = "頭像3.jpg";
ThreadsDemo6 t1= new ThreadsDemo6(url1,name1);
ThreadsDemo6 t2= new ThreadsDemo6(url1,name2);
ThreadsDemo6 t3= new ThreadsDemo6(url1,name3);
//建立執行服務
ExecutorService executorService= Executors.newFixedThreadPool(3);
//提交執行
Future<Boolean> r1 =executorService.submit(t1);
Future<Boolean> r2 =executorService.submit(t2);
Future<Boolean> r3 =executorService.submit(t3);
//獲取結果
Boolean rs1 = r1.get();
Boolean rs2 = r2.get();
Boolean rs3 = r3.get();
//關閉服務
executorService.shutdownNow();
}
}
執行緒併發
發現問題
多個執行緒操作同一個資源識,執行緒不安全,資料紊亂
public class ThreadsDemo4 implements Runnable{
private int ticketNum = 10;
@Override
public void run() {
while (true){
if (ticketNum <1 ) {
break;
}
System.out.println( Thread.currentThread().getName()+ "===>拿了第"+ticketNum-- +"票");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
ThreadsDemo4 ticket = new ThreadsDemo4();
new Thread(ticket, "XiaoMing").start();
new Thread(ticket, "XiaoHong").start();
new Thread(ticket, "HuangNiu").start();
}
}
加深對多執行緒的印象——模擬龜兔賽跑
public class ThreadsDemo5 implements Runnable {
//勝利者
private static String winner;
//跑道長度
private static int RUNWAY_LENGTH = 50;
//遊戲結束標誌
boolean gameOver(int i){
//勝者唯一
if (winner!=null){
return true;
}
if( i >= RUNWAY_LENGTH){
winner = Thread.currentThread().getName();
System.out.println("===比賽結束==="+"\n"+winner+"-->獲得了勝利");
return true;
}
return false;
}
@Override
public void run() {
for (int i = 0; i <= RUNWAY_LENGTH; i++) {
boolean flag = gameOver(i);
if (flag) {
break;
}
String name = Thread.currentThread().getName();
System.out.println(name + "-->已經跑了" + i + "米");
//兔子跑的快
if ("兔子".equals(name)){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//烏龜爬的慢
if ("烏龜".equals(name)) {
System.out.println("加油!!!!");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//兔子半路睡著
if ("兔子".equals(name) && i == RUNWAY_LENGTH/2){
System.out.println("怎麼能睡覺呢?\n");
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ThreadsDemo5 race = new ThreadsDemo5();
new Thread(race,"兔子").start();
new Thread(race,"烏龜").start();
}
}