Java多线程精讲(非高并发-授课专用)附synchronized
Java多線程精講(非高并發-授課專用)
目錄
程序,進程,線程的基本概念
start與run的區別
函數測試demo:?
創建線程(一)【new Thread()】
創建線程(二)【extends Thread】
創建線程(三)【implements Runnable】
線程無交互測試:【run】
線程無交互測試:【start】
加強交互:【加上sleep休息時間?】
游戲編寫:【王語嫣大戰表哥·慕容復】
synchronized
程序,進程,線程的基本概念
程序:是為完成特定任務,用某種語言編寫的一組指令的集合,即指一段靜態的代碼,靜態對象。
進程:是程序的一次執行過程,或是正在運行的一個程序,是一個動態的過程,有它自身的產生,存在和消亡的過程。——生命周期。
線程:進程可進一步細化為線程,是一個程序內部的一條執行路徑。
即:線程《線程(一個程序可以有多個線程)
程序:靜態的代碼 進程:動態執行的程序
線程:進程中要同時干幾件事時,每一件事的執行路徑成為線程。
附:
并行:多個CPU同時執行多個任務,比如:多個人同時做不同的事。
并發:一個CPU(采用時間片)同時執行多個任務,比如秒殺平臺,多個人做同件事?
線程的相關API
//獲取當前線程的名字 currentThread();靜態方法,返回執行當前代碼的線程 Thread.currentThread().getName();獲取當前線程的名字 Thread.currentThread().setName();設置當前線程的名字 sleep(long millitime);線程休眠一段時間 start();1.啟動當前線程2.調用線程中的run方法 run();通常需要重寫Thread類中的此方法,將創建的線程要執行的操作聲明在此方法中 join();線程等待·卡死的等待。 isAlive();判斷當前線程是否存活start與run的區別
用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。通過調用Thread類的start()方法來啟動一個線程,這時此線程處于就緒(可運行)狀態,并沒有運行,一旦得到cpu時間片,就開始執行run()方法,這里方法run()稱為線程體,它包含了要執行的這個線程的內容,run方法運行結束,此線程隨即終止。
函數測試demo:?
package test; /*** * @author laoshifu* @date 2021年12月5日**/ public class Main {public static void main(String[] args) throws InterruptedException {//修改線程名城Thread.currentThread().setName("superMan");//獲取線程名稱String name = Thread.currentThread().getName();System.out.println(name);//當前線程是否存在boolean b = Thread.currentThread().isAlive();System.out.println(b);//創建多線程Thread t = new Thread() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(i);}}};//啟動多線程t.run();//線程等待Thread.currentThread().join();//休息Thread.sleep(2000);//某線程是否存在System.out.println(t.isAlive());} }創建線程(一)【new Thread()】
這里繼承Thread類的方法是比較常用的一種,如果說你只是想起一條線程。沒有什么其它特殊的要求,那么可以使用Thread
//創建多線程Thread t = new Thread() {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(i);}}};//啟動多線程t.run();創建線程(二)【extends Thread】
package test;public class Thread_test extends Thread{@Overridepublic void run() {currentThread().setName("orange");for (int i = 0; i < 100; i++) {System.out.println(currentThread().getName()+":"+i);}} } package test;/*** @author laoshifu* @date 2021年12月5日*/ public class Main {public static void main(String[] args) {Thread_test test = new Thread_test();test.run();} } }創建線程(三)【implements Runnable】
采用Runnable也是非常常見的一種,我們只需要重寫run方法即可。下面也來看個實例。
package test;public class Thread_te implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("Runnable"+":"+i);}}} package test;/*** @author laoshifu* @date 2021年12月5日*/ public class Main {public static void main(String[] args) {Thread t1 = new Thread(new Thread_te());t1.start();} }}??
如果一個類繼承Thread,則不適合資源共享。但是如果實現了Runable接口的話,則很容易的實現資源共享。
線程無交互測試:【run】
package test;/*** @author laoshifu* @date 2021年12月5日*/ public class Main {public static void main(String[] args) {Thread_test test = new Thread_test();test.run();Thread_test2 test2 = new Thread_test2();test2.run();Thread t3 = new Thread(new Thread_te());t3.start();} }無交互
線程無交互測試:【start】
package test;/*** @author laoshifu* @date 2021年12月5日*/ public class Main {public static void main(String[] args) {Thread_test test = new Thread_test();Thread_test2 test2 = new Thread_test2();Thread t3 = new Thread(new Thread_te());System.out.println("開啟一");test.start();System.out.println("開啟二");test2.start();System.out.println("開啟三");t3.start();} }加強交互:【加上sleep休息時間】
總結:
實現Runnable接口比繼承Thread類所具有的優勢:
1):適合多個相同的程序代碼的線程去處理同一個資源
2):可以避免java中的單繼承的限制
3):增加程序的健壯性,代碼可以被多個線程共享,代碼和數據獨立
游戲編寫:【王語嫣大戰表哥·慕容復】
package test;import java.util.Random; import java.util.Scanner;/*** @author laoshifu* @date 2021年12月5日*/ public class Main {static String name = "王語嫣";static String bossName = "表哥·慕容復";/*** 王語嫣攻擊力*/static int A_AC = 500;/*** 表哥·慕容復血量*/static int B_HP = 100000;public static void main(String[] args) {System.out.println("戰斗開始");System.out.println("**********************");System.out.println("***1、增加10%戰斗力****");System.out.println("***2、BOSS血量增加10%**");System.out.println("**********************");new Thread() {public void run() {Random ra = new Random();while (true) {int Cut = A_AC + ra.nextInt(A_AC);B_HP -= Cut;String s = String.format("%s對%s造成%s點傷害,%s血量剩余%s", name, bossName, Cut, bossName, B_HP);System.out.println(s);if (B_HP <= 0) {System.out.printf("終于干掉了%s,可以和段公子長相廝守了。", bossName);//游戲停止System.exit(0);}try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}};}.start();new Thread() {@SuppressWarnings("resource")public void run() {Scanner sc = new Scanner(System.in);while (true) {switch (sc.next()) {case "1":A_AC+=(A_AC/10);System.out.println(name+"攻擊增加10%,當前"+name+"攻擊力"+A_AC);break;case "2":B_HP+=(B_HP/10);System.out.println(bossName+"血量增加10%,當前血量"+B_HP);break;default:break;}}};}.start();} }?
?synchronized【Java】中使用的demo
沒有synchronized的效果:
package Action;public class syn {static int count=10;static Object lock=new Object();public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {while (true) {if(count<=0) {System.out.println("內部線程:結束");break;} // synchronized(lock) {count--;System.out.println("內部線程:"+count); // }try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}).start();while (true) {if(count<=0) {System.out.println("外部線程:結束");break;} // synchronized (lock) {count--;System.out.println("外部線程:"+count); // }try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} }很明顯,在沒有使用【鎖】的時候數據出現了錯誤。?
synchronized
有synchronized的效果:
package Action;public class syn {static int count=10;static Object lock=new Object();public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {while (true) {if(count<=0) {System.out.println("內部線程:結束");break;}synchronized(lock) {count--;System.out.println("內部線程:"+count);}try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}).start();while (true) {if(count<=0) {System.out.println("外部線程:結束");break;}synchronized (lock) {count--;System.out.println("外部線程:"+count);}try {Thread.sleep(100);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} }效果很明顯,沒有數據錯誤。?
?synchronized不僅可以修飾代碼塊,還可以修飾方法、實例對象、class對象。
如果鎖的是類對象的話,盡管new多個實例對象,但他們仍然是屬于同一個類依然會被鎖住,即線程之間保證同步關系,以上的游戲demo可以使用【synchronized】鎖定慕容復的血量。
希望可以使大家對【多線程】增加一定的理解。
歡迎一鍵三連。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Java多线程精讲(非高并发-授课专用)附synchronized的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【PHP7.2+】win10安装lara
- 下一篇: jQuery综合案例——打地鼠(教学版本