【Java多线程】轻松搞定Java多线程(一)
生活随笔
收集整理的這篇文章主要介紹了
【Java多线程】轻松搞定Java多线程(一)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
輕松搞定Java多線程(一)
- Java多線程詳解(一)
- 1、 線程簡(jiǎn)介
- 2、線程的創(chuàng)建
- 2.1 三種創(chuàng)建方式
- 2.2 Thread
- 2.3 實(shí)現(xiàn)Runnable
- 2.3.1 初識(shí)并發(fā)問題
- 2.3.2 案例:龜兔賽跑
- 2.4 實(shí)現(xiàn)Callable接口
- 3、靜態(tài)代理模式
- 4、Lambda表達(dá)式
- 4.1 推導(dǎo)lambda表達(dá)式
- 4.2 簡(jiǎn)化lambda表達(dá)式
Java多線程詳解(一)
1、 線程簡(jiǎn)介
注意:很多多線程是模擬出來的,真正的多線程是指有多個(gè)cpu,即多核。如果是模擬出來的多線程,即在一個(gè)cpu的情況下,在同一個(gè)時(shí)間點(diǎn),cpu只能執(zhí)行一個(gè)代碼,因?yàn)榍袚Q的很快。所以有同時(shí)執(zhí)行的錯(cuò)覺。
- 線程就是獨(dú)立的執(zhí)行路徑;
- 在程序運(yùn)行時(shí),即使沒有自己創(chuàng)建線程,后臺(tái)也會(huì)有多個(gè)線程,如主線程,gc線程;
- main()稱之為主線程,為系統(tǒng)的入口,用于執(zhí)行整個(gè)程序;
- 在一個(gè)進(jìn)程中,如果開辟了多個(gè)線程,線程的運(yùn)行由調(diào)度器安排調(diào)度,調(diào)度器是與操作系統(tǒng)緊密相關(guān)的,先后順序是不能人為干預(yù)的;
- 對(duì)同一份資源操作時(shí),會(huì)存在資源搶奪的問題,需要加入并發(fā)控制;
- 線程會(huì)帶來額外的開銷,如cpu調(diào)度時(shí)間,并發(fā)控制開銷;
- 每個(gè)線程在自己的工作內(nèi)存交互,內(nèi)存控制不當(dāng)會(huì)造成數(shù)據(jù)不一致。
2、線程的創(chuàng)建
2.1 三種創(chuàng)建方式
2.2 Thread
- 自定義線程類繼承Thread類
- 重寫run()方法,編寫線程執(zhí)行體
- 創(chuàng)建線程對(duì)象,調(diào)用start()方法啟動(dòng)線程
執(zhí)行結(jié)果:
2.3 實(shí)現(xiàn)Runnable
- 定義MyRunnable類實(shí)現(xiàn)Runable接口
- 實(shí)現(xiàn)run()方法,編寫程序執(zhí)行體
- 創(chuàng)建線程對(duì)象,調(diào)用start()方法啟動(dòng)線程
小結(jié):
- 繼承Thread類
- 子類繼承Thread類具備多線程能力
- 啟動(dòng)線程:子類對(duì)象.start();
- 不建議使用:避免OOP單繼承局限性
- 實(shí)現(xiàn)Runnable接口
- 實(shí)現(xiàn)接口Runnable具有多線程的能力
- 啟動(dòng)線程:傳入目標(biāo)對(duì)象+Thread對(duì)象.start();
- 推薦使用:避免單繼承局限性,靈活方便,方便同一個(gè)對(duì)象被多個(gè)線程使用
2.3.1 初識(shí)并發(fā)問題
/*** 多個(gè)線程同時(shí)操作一個(gè)對(duì)象* 買火車票的例子*//*** 發(fā)現(xiàn)問題:* 多個(gè)線程操作同一個(gè)資源的情況下,線程不安全,數(shù)據(jù)紊亂*/ public class TestThread4 implements Runnable {/*** 票數(shù)*/private int ticketsNums = 20;@Overridepublic void run() {while (true) {if (ticketsNums <= 0) {break;}/*** 模擬延時(shí)*/try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "拿到了" + ticketsNums-- + "票");}}public static void main(String[] args) {TestThread4 ticket = new TestThread4();new Thread(ticket, "小明").start();new Thread(ticket, "老師").start();new Thread(ticket, "黃牛").start();} }2.3.2 案例:龜兔賽跑
/*** 模擬龜兔賽跑*/ public class Race implements Runnable {/*** 勝利者*/private static String winner;@Overridepublic void run() {for (int i = 0; i <= 100; i++) {/*** 模擬兔子睡覺*/if (Thread.currentThread().getName().equals("兔子") && i%10 == 0) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}/*** 判斷比賽是否結(jié)束*/boolean flag = gameOver(i);/*** 如果比賽結(jié)束,退出程序*/if (flag) {break;}System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");}}/*** 判斷是否完成比賽*/private boolean gameOver(int steps) {/*** 判斷是否有勝利者*/if (winner != null) {return true;} else if (steps >= 100){winner = Thread.currentThread().getName();System.out.println("winner is " + winner);return true;}return false;}public static void main(String[] args) {Race race = new Race();new Thread(race, "兔子").start();new Thread(race, "烏龜").start();} }2.4 實(shí)現(xiàn)Callable接口
Callable的好處:
3、靜態(tài)代理模式
靜態(tài)代理模式總結(jié):
真實(shí)對(duì)象和代理對(duì)象都要實(shí)現(xiàn)同一個(gè)接口
代理對(duì)象代理真實(shí)角色
好處:
代理對(duì)象可以做很多真實(shí)對(duì)象做不了的事情
真實(shí)對(duì)象專注做自己的事情
/*** Jack結(jié)婚的例子,婚慶公司幫助Jack結(jié)婚*/ public class StaticProxy {public static void main(String[] args) {WeddingCompany weddingCompany = new WeddingCompany(new Jack());weddingCompany.HappyMarry();}}interface Marry {void HappyMarry(); }/*** 真實(shí)角色*/ class Jack implements Marry {@Overridepublic void HappyMarry() {System.out.println("Jack要結(jié)婚了");} }/*** 代理角色*/ class WeddingCompany implements Marry {private Marry target;public WeddingCompany(Marry target) {this.target = target;}@Overridepublic void HappyMarry() {before();this.target.HappyMarry();after();}private void before() {System.out.println("結(jié)婚之前,布置現(xiàn)場(chǎng)");}private void after() {System.out.println("結(jié)婚之后,收拾東西");} }4、Lambda表達(dá)式
- 其實(shí)質(zhì)屬于函數(shù)式編程的概念
- 為什么要使用lambda表達(dá)式
- 避免匿名內(nèi)部類定義過多
- 可以讓你的代碼看起了很簡(jiǎn)潔
- 去掉了一堆沒有意義的代碼,只留下核心的邏輯
-
函數(shù)式接口的定義:
- 任何接口,如果只包含唯一一個(gè)抽象方法,那么它就是一個(gè)函數(shù)式接口。
- 對(duì)于函數(shù)式接口,我們可以通過lambda表達(dá)式來創(chuàng)建該接口的對(duì)象。
4.1 推導(dǎo)lambda表達(dá)式
/*** 推導(dǎo)lambda表達(dá)式*/ public class TestLambda1 {/*** 3.靜態(tài)內(nèi)部類*/static class Like2 implements ILike {@Overridepublic void lambda() {System.out.println("I Like Lambda2");}}public static void main(String[] args) {ILike like = new Like();like.lambda();like = new Like2();like.lambda();/*** 4.局部?jī)?nèi)部類*/class Like3 implements ILike {@Overridepublic void lambda() {System.out.println("I Like Lambda3");}}like = new Like3();like.lambda();/*** 5.匿名內(nèi)部類,沒有類的名稱,必須借助接口或者父類*/like = new ILike() {@Overridepublic void lambda() {System.out.println("I Like Lambda4");}};like.lambda();/*** 6.用lambda簡(jiǎn)化*/like = () -> {System.out.println("I Like Lambda5");};like.lambda();}/*** 1.定義一個(gè)函數(shù)式接口*/interface ILike {void lambda();}/*** 2.實(shí)現(xiàn)類*/static class Like implements ILike {@Overridepublic void lambda() {System.out.println("I Like Lambda");}} }4.2 簡(jiǎn)化lambda表達(dá)式
public class TestLambda2 {public static void main(String[] args) {ILove love = new Love();love.love(1);love = (int a) -> {System.out.println("I Love Lambda-->" + a);};love.love(2);/*** 簡(jiǎn)化1:參數(shù)類型*/love = (a) -> {System.out.println("I Love Lambda-->" + a);};love.love(3);/*** 簡(jiǎn)化2:簡(jiǎn)化括號(hào)*/love = a -> {System.out.println("I Love Lambda-->" + a);};love.love(4);/*** 簡(jiǎn)化3:簡(jiǎn)化花括號(hào)*/love = a -> System.out.println("I Love Lambda-->" + a);love.love(5);} }interface ILove {void love(int a); }class Love implements ILove {@Overridepublic void love(int a) {System.out.println("I Love Lambda-->" + a);} }總結(jié):
總結(jié)
以上是生活随笔為你收集整理的【Java多线程】轻松搞定Java多线程(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于STM32的智能循迹避障小车
- 下一篇: Java-反射