Java車票,車站,生命周期,龜兔賽跑,同步鎖,禮讓,守護線程,挖金礦【詩書畫唱】
個人理解:加同步鎖等的時候,就可以讓線程”按順序排隊“,一個一個地?fù)孋PU,一個搶完對應(yīng)的每次有的CPU了,另一個才搶對應(yīng)的每次有的CPU,解決”并發(fā)“問題。
自己寫的禮讓(個人的理解:禮讓就是選擇放棄獨占CPU,選擇和其他線程分享搶到的CPU)
例子題目:打印循環(huán)累加1的num,用上同步鎖使之不亂序(個人的理解:同步鎖的作用等就是讓打印的線程啟動等后的結(jié)果,不是亂序,而是有序,有邏輯和規(guī)律的)
:

/**
?*?
?*/
package thread;
import java.util.Random;
public class jinKuang {
public static void main(String[] args) throws Exception{
personClass personClass=new personClass();
new Thread(personClass, "三連").start();
new Thread(personClass, "關(guān)注").start();
new Thread(personClass, "詩書畫唱").start();
}
}
class personClass implements Runnable{
static int num=0;
@Override
public void run() {
while(true){
synchronized (this) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
num++;
System.out.println(Thread.currentThread()
.getName()+"搶到當(dāng)前CPU,現(xiàn)在num的值為"+num);
// 個人理解:禮讓就是選擇放棄獨占CPU,
// 選擇和其他線程分享搶到的CPU
if(num%5==0){
Thread.yield();
// yield 英[ji?ld]
// 美[ji?ld]
// v. 出產(chǎn)(作物); 產(chǎn)生(收益、效益等);
// 提供; 屈服; 讓步; 放棄; 繳出;
// n. 產(chǎn)量; 產(chǎn)出; 利潤;
System.out.println(Thread.currentThread()
.getName()+"進行了禮讓");
}
if(num==100){
try {
Thread.sleep(10);
System.out.println("休息一下");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(num==200){
break;
}
}
}
}
}






設(shè)計一個線程,模擬買票場景,現(xiàn)有100張票,
??使用3個線程進行購買車票
方法一:

package thread;
import java.util.Random;
public class cheZhan {
public static void main(String[] args) throws Exception{
chePiaoClass chePiaoClass=new chePiaoClass() ;
// 下面是省了重命名的部分,直接new實例化:
new Thread(chePiaoClass, "長沙站").start();
new Thread(chePiaoClass, "北京站").start();
new Thread(chePiaoClass,"山東站").start();
}
}
class chePiaoClass implements Runnable{
static int piaoShu=100;//總票數(shù)
public void run() {
//票數(shù)大于0就可以賣票:
while(piaoShu>0){
// 加synchronized的話,打印出來的才
// 會有從大到小等的順序等。
// 不然的話,打印出的內(nèi)容等就會很亂,
// 這是安全性出了問題
synchronized (this) {
// synchronized關(guān)鍵字是用來控制線程同步的,
// 就是在多線程的環(huán)境下,
// 控制synchronized代碼段不被多個線程同時執(zhí)行。
//
// synchronized是Java中的關(guān)鍵字,是一種同步鎖。
// synchronized:
// 英[?s??kr?na?zd]
// 美[?s??kr?na?zd]
// v. (使) 同步,在時間上一致,同速進行
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(piaoShu>0){
System.out.println(Thread.currentThread()
.getName()+"賣出了第"+piaoShu+"張票");
}piaoShu--;}
}
}
}


方法二:

package thread;
import java.util.Random;
public class piao implements Runnable{
?static int num;
?static int count;
?piao(){
? num = 100;
? count = 0;
?}
?
?@Override
?public void run() {
? ? ?while(num > 0){
? ? ? synchronized (this) {
? ? try{
? ? ?Thread.sleep(new Random().nextInt(20));
? ? }catch(Exception e){
? ? ?e.printStackTrace();
? ? }
? ??
? ? if(num > 0){
? ? System.out.println(Thread.currentThread().getName()
? ? +"_____買的票數(shù)號碼"+num);
? ? num --;
? ? count ++;}
? ?}
? ? ?}
??
?}
?
?public static void main(String[] args){
? piao ticket = new piao();
? for(int line = 1 ; line <= 3 ; line ++){
? ?new Thread(ticket,"線程名:線程"+line).start();
? }
?}
}


創(chuàng)建一個兔子類,一個烏龜類,進行賽跑,目標(biāo)為10米,
兔子每跑1米休息0.05秒,規(guī)定生成隨機數(shù),兔子生成的隨機數(shù)范圍為0-5,生成的隨機數(shù)為3時才開始跑一米,烏龜生成的隨機數(shù)范圍0-20,生成的隨機數(shù)為13的時候才開始跑一米,烏龜每跑一米休息0.01秒 ,使用線程模擬這個特定龜兔賽跑的過程:

/**
?*?
?*/
package thread;
import java.util.Random;
public class tuZi {
//垃圾回收線程:
// 執(zhí)行垃圾回收的線程,稱為垃圾回收線程。
public static void main(String[] args) throws Exception{
// 2.創(chuàng)建一個兔子類,一個烏龜類,進行賽跑,目標(biāo)為10米,
// 兔子每跑1米休息0.05秒,兔子的隨機范圍為0-5,隨機到3開始跑,
//? 烏龜隨機范圍0-20,隨機到13的時候開始跑,
// 烏龜沒跑一米休息0.01秒 ,使用線程模擬
wuGuiClass wuGuiClass=new wuGuiClass();
new Thread(wuGuiClass,"烏龜").start();
tuZiClass tuZiClass=new tuZiClass();
new Thread(tuZiClass,"兔子").start();
}
}
class wuGuiClass implements Runnable{
static int weiZhi=0;//:開始的位置為0米的位置
Random RandomNum=new Random();
public void run() {
while(true){//如果沒有到終點一直跑
//烏龜每跑一米休息0.01秒
//設(shè)置他們跑的速度就用隨機數(shù)去設(shè)置
int shuzi=RandomNum.nextInt(25);
System.out.println("烏龜生成的隨機數(shù)為"+shuzi);
//烏龜隨機到13之后才開始跑
if(shuzi==13){
weiZhi++;//每次生成的隨機數(shù)為13時跑一米
System.out.println("烏龜共跑了"+weiZhi+"米");
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//烏龜或者兔子不管誰到終點,都用break停止所有線程
if(wuGuiClass.weiZhi>=10||tuZiClass.weiZhi>=10){
//怎么判斷誰贏了
if(wuGuiClass.weiZhi>=10){
System.out.println("烏龜勝利");
}
if(tuZiClass.weiZhi>=10){
System.out.println("兔子勝利");
}
break;
}
}
}
}
class tuZiClass implements Runnable{
static int weiZhi=0;//開始的位置為0米的位置
Random RandomNum=new Random();
public void run() {
while(true){//如果沒有到終點一直跑,
//兔子每跑一米休息0.05秒,用上sleep
int tuZiNum=RandomNum.nextInt(5);
System.out.println("兔子生成的隨機數(shù)為了"+tuZiNum);
if(tuZiNum==3){
weiZhi++;//每次生成的隨機數(shù)為3時跑一米
System.out.println("兔子共跑了"+weiZhi+"米");
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(wuGuiClass.weiZhi>=10||tuZiClass.weiZhi>=10){
//用兩個if判斷誰贏了
if(wuGuiClass.weiZhi>=10){
System.out.println("烏龜勝利");
}
if(tuZiClass.weiZhi>=10){
System.out.println("兔子勝利");
}
break;
}
}
}
}



簡述線程的生命周期
生命周期由4種狀態(tài)組成:
1.就緒狀態(tài):實例化好了這個線程,但是并沒有啟動這個線程
2.可運行狀態(tài):啟動了這個線程,但是這個線程并沒有搶到cpu的使用權(quán)
3.運行狀態(tài):這個線程搶到了cpu的使用權(quán)
4.死亡狀態(tài):這個線程的代碼全部執(zhí)行完畢之后,就釋放掉這個線程
//創(chuàng)建一個兔子類,一個烏龜類,進行賽跑,
//目標(biāo)為100米,
//(1)兔子每 0.1 秒 5 米的速度,每跑20米休息0.1秒;
//(2)烏龜每 0.1 秒跑 2 米的速度,不休息,烏龜一直跑,使用線程模擬;


JS中回調(diào)函數(shù)(callback)理解:
字面上理解下來就是,回調(diào)就是一個函數(shù)的調(diào)用過程。那么就從理解這個調(diào)用過程開始吧。函數(shù)a有一個參數(shù),這個參數(shù)是個函數(shù)b,當(dāng)函數(shù)a執(zhí)行完以后執(zhí)行函數(shù)b。那么這個過程就叫回調(diào)。
其實中文也很好理解:回調(diào),回調(diào),就是回頭調(diào)用的意思。函數(shù)a的事先干完,回頭再調(diào)用函數(shù)b。
舉個現(xiàn)實的例子:約會結(jié)束后你送你女朋友回家,離別時,你肯定會說:“到家了給我發(fā)條信息,我很擔(dān)心你?!睂Σ?,然后你女朋友回家以后還真給你發(fā)了條信息。小伙子,你有戲了。
其實這就是一個回調(diào)的過程。你留了個函數(shù)b(要求女朋友給你發(fā)條信息)給你女朋友,然后你女朋友回家,回家的動作是函數(shù)a。她必須先回到家以后,函數(shù)a的內(nèi)容執(zhí)行完了,再執(zhí)行函數(shù)b,然后你就收到一條信息了。
這里必須清楚一點:函數(shù)b是你以參數(shù)形式傳給函數(shù)a的,那么函數(shù)b就叫回調(diào)函數(shù)。
?也許有人有疑問了:一定要以參數(shù)形式傳過去嗎,我不可以直接在函數(shù)a里面調(diào)用函數(shù)b嗎?確實可以。求解中。
解惑:如果你直接在函數(shù)a里調(diào)用的話,那么這個回調(diào)函數(shù)就被限制死了。但是使用函數(shù)做參數(shù)就有下面的好處:當(dāng)你a(b)的時候函數(shù)b就成了回調(diào)函數(shù),而你還可以a(c)這個時候,函數(shù)c就成了回調(diào)函數(shù)。如果你寫成了function a(){...;b();}就失去了變量的靈活性。
含個人的超級詳細(xì)的解析:

//創(chuàng)建一個兔子類,一個烏龜類,進行賽跑,
//目標(biāo)為100米,
//(1)兔子每 0.1 秒 5 米的速度,每跑20米休息0.1秒;
//(2)烏龜每 0.1 秒跑 2 米的速度,不休息,烏龜一直跑,使用線程模擬;
package thread;
import java.util.Random;
import thread.Animal.Calltoback;
public class guiTuGame {
public static void main(String[] args) throws Exception{
// 實例化烏龜和兔子:
//tortoise 英[?t??t?s]
//美[?t??rt?s]
//n. 陸龜; 龜;
//————————————
//rabbit 英[?r?b?t]
//美[?r?b?t]
//n. 兔; 野兔; 兔肉;
//v. 獵兔; 捕兔;
? ? ? ? wuGuiDeClass wuGuiDeClass = new wuGuiDeClass();
??
? ? ? ? rabbitClass rabbitClass = new rabbitClass();
? ? ? ? // 回調(diào)方法的使用,誰先調(diào)用calltoback方法,另一個就不跑了
? ? ? ??
//? ? ? ? 回調(diào)就是一個函數(shù)的調(diào)用過程。"call to back":"叫其回來"
//? ? ? ? 那么就從理解這個調(diào)用過程開始吧。
//? ? ? ? 函數(shù)a有一個參數(shù),這個參數(shù)是個函數(shù)b,
//? ? ? ? 當(dāng)函數(shù)a執(zhí)行完以后執(zhí)行函數(shù)b。
//? ? ? ? 那么這個過程就叫回調(diào)。? ?
//? ? ? ? LetLoserStop:讓敗者停止線程的開啟? ?
? ? ? ??
? ? ? ??
//? ? ? 當(dāng)wuGuiDeClass wuGuiDeClass = new wuGuiDeClass();
//? ? ? 部分的線程先結(jié)束(烏龜贏)時,
//? ? ? ? 就會wuGuiDeClass傳值
//? ? ? ? 到回執(zhí)函數(shù),就會執(zhí)行下面的一句的回執(zhí)函數(shù)等,
//? ? ? ? calltoback != null,
//? ? ? ? 就會執(zhí)行烏龜類中的 calltoback.win();
//? ? ? ? 讓兔子類的也再次執(zhí)行一次回執(zhí)函數(shù),讓兔子停止
? ? ??
? ? ? ? LetLoserStop letLoserStopWuGui =
? ? ? ? new LetLoserStop(wuGuiDeClass);
? ? ? ? // 讓兔子的回調(diào)方法里面存在烏龜對象的值,可以把烏龜停止stop:
? ? ? ? rabbitClass.calltoback =?
? ? ? ? letLoserStopWuGui;
? ? ? ??
? ? ? ??
? ? ? ? LetLoserStop letLoserStopRabbit =
? ? ? ? new LetLoserStop(rabbitClass);
? ? ? ? // 讓烏龜?shù)幕卣{(diào)方法里面存在兔子對象的值,可以把兔子停止stop:
? ? ? ? wuGuiDeClass.calltoback = letLoserStopRabbit;
? ? ? ? // 開始跑:
? ? ? ? wuGuiDeClass.start();
? ? ? ? rabbitClass.start();
}
}
//LetOneStop:讓一個停止
//當(dāng)有一個到達(dá)終點的時候,需要讓沒到終點的烏龜或兔子的線程停止
//,不然的話就會有這里"烏龜獲得了勝利"和
//"兔子獲得了勝利"都打印出來,所以要用回調(diào)函數(shù)
//Calltoback,當(dāng)兔子和烏龜?shù)木€程執(zhí)行時,有一方到達(dá)時候,就把
//這一方的參數(shù)傳到回調(diào)函數(shù),讓回調(diào)函數(shù)中聲明的stop方法起效果
class LetLoserStop implements Calltoback {
? ? // 動物對象
? ? Animal loserClass;
?
? ? // 獲取動物對象,可以傳入兔子或烏龜?shù)膶嵗?/p>
? ? public LetLoserStop(Animal loserClass) {
? ? ? ? this.loserClass = loserClass;
? ? }
?
? ? // 讓動物的線程停止:
? ? public void win() {
? ? ? ? // 線程停止用stop方法:
? ? ? ? loserClass.stop();
? ? }
}
class wuGuiDeClass extends Animal {
? ? public wuGuiDeClass() {
? ? ? ? setName("烏龜");// Thread的方法,給線程賦值名字
? ? }
?
? ? // 重寫running方法,編寫烏龜?shù)谋寂懿僮?/p>
? ? @Override
? ? public void runing() {
? ? ? ? // x:烏龜?shù)奈灰?
? ? ? ? int x = 2;
? ? ? ? length -= x;
? System.out.println("烏龜跑了" +
? ? ? ? x + "米,距離終點還有" + length + "米");
? ? ? ? if (length <= 0) {
? ? ? ? ? ? length = 0;
? ? ? ? ? ? System.out.println("烏龜獲得了勝利");
? ? ? ? ? ? // 讓兔子不要在跑了
? ? ? ? ? ? if (calltoback != null) {
? ? ? ? ? ? ? ? calltoback.win();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? try {
? ? ? ? ? ? sleep(100);? ?
? ? ? ? ? ? //每0.1秒跑2米,用sleep實現(xiàn)速度的效果
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
?
}
class rabbitClass extends Animal {
?
? ? public rabbitClass() {
? ? ? ? setName("兔子");
? ? }
?
? ? @Override
? ? public void runing() {
? ? ? ? //X:兔子位移:
? ? ? ? int x = 5;
? ? ? ? length -= x;
?
? ? ? ? System.out.println("兔子跑了" + x?
? ? ? ? + "米,距離終點還有" + length + "米");
? ? ? ? if (length <= 0) {
? ? ? ? ? ? length = 0;
? ? ? ? ? ? System.out.println("兔子獲得了勝利");
? ? ? ? ? ? // 給回調(diào)對象賦值,讓烏龜不要再跑了
? ? ? ? ? ? if (calltoback != null) {
? ? ? ? ? ? ? ? calltoback.win();
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? try {
? ? ? ? ? ? if ((2000 - length) % 20 == 0) {? ?
? ? ? ? ? ? // 每20米休息一次,休息時間是0.1秒
? ? ? ? ? ? ? ? sleep(100);
? ? ? ? ? ? } else {? ? ? ? ? ? ? ? //每0.1秒跑5米
? ? ? ? ? ? ? ? sleep(100);
? ? ? ? ? ? }
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
?
}
//這里用動物類繼承了線程類就
//可以有線程類等的特性等,在主函數(shù)傳兔子類或烏龜類時,就不會報錯等
abstract class Animal extends Thread {
? ? public int length = 100;// 比賽長度
?
? ? public abstract void runing();
?
? ? @Override
? ? public void run() {
? ? ? ? super.run();
? ? ? ? while (length > 0) {
? ? ? ? ? ? runing();
? ? ? ? }
? ? }
?
? ? // 在需要回調(diào)數(shù)據(jù)的地方(兩個子類需要),聲明一個接口
? ? public static interface Calltoback {
? ? ? ? public void win();
? ? }
?
? ? // 2.創(chuàng)建接口對象
? ? public Calltoback calltoback;
?
}


創(chuàng)建一個人物類,創(chuàng)建人物張三和李四共同去挖礦,用一個數(shù)字5代表金礦,聲明隨機數(shù),當(dāng)挖到金礦的時候,當(dāng)前線程打印“呵呵,挖到金礦了”并且禮讓線程,一共挖30次金礦,統(tǒng)計每個人挖到金礦的次數(shù)。

/**
?*?
?*/
package thread;
import java.util.Random;
public class jinKuangClass {
public static void main(String[] args) throws Exception{
personClassJinKuang personClass=
new personClassJinKuang();
new Thread(personClass, "張三").start();
new Thread(personClass, "李四").start();
}
}
class personClassJinKuang implements Runnable{
static int num=0;
Random RandomNum=new Random();
@Override
public void run() {
while(true){
int tuZiNum=RandomNum.nextInt(10);
System.out.println("生成的隨機數(shù)為"+tuZiNum);
synchronized (this) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(tuZiNum==5){
num++;
System.out.println(Thread.currentThread()
.getName()+"搶到當(dāng)前CPU,現(xiàn)在挖到的金礦次數(shù)為"+num+"次");
// 個人理解:禮讓就是選擇放棄獨占CPU,
// 選擇和其他線程分享搶到的CPU
if(num%5==0){
Thread.yield();
// yield 英[ji?ld]
// 美[ji?ld]
// v. 出產(chǎn)(作物); 產(chǎn)生(收益、效益等);
// 提供; 屈服; 讓步; 放棄; 繳出;
// n. 產(chǎn)量; 產(chǎn)出; 利潤;
System.out.println(Thread.currentThread()
.getName()+"進行了禮讓");
}}
if(num==100){
try {
Thread.sleep(100);
System.out.println("休息一下");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(num>=200){
break;
}
}
}
}
}



個人對守護線程的理解:

