欢迎光临散文网 会员登陆 & 注册

Java车票,车站,生命周期,龟兔赛跑,同步锁,礼让,守护线程,挖金矿【诗书画唱】

2020-07-24 16:16 作者:诗书画唱  | 我要投稿

个人理解:加同步锁等的时候,就可以让线程”按顺序排队“,一个一个地抢CPU,一个抢完对应的每次有的CPU了,另一个才抢对应的每次有的CPU,解决”并发“问题。

自己写的礼让(个人的理解:礼让就是选择放弃独占CPU,选择和其他线程分享抢到的CPU)



例子题目:打印循环累加1的num,用上同步锁使之不乱序(个人的理解:同步锁的作用等就是让打印的线程启动等后的结果,不是乱序,而是有序,有逻辑和规律的)






/**

 * 

 */

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, "关注").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()+"抢到当前CPU,现在num的值为"+num);

// 个人理解:礼让就是选择放弃独占CPU,

// 选择和其他线程分享抢到的CPU

if(num%5==0){

Thread.yield();

// yield 英[jiːld]

// 美[jiːld]

// v. 出产(作物); 产生(收益、效益等);

// 提供; 屈服; 让步; 放弃; 缴出;

// 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;

}

}

}

}

}






设计一个线程,模拟买票场景,现有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;//总票数

public void run() {

//票数大于0就可以卖票:

while(piaoShu>0){

// 加synchronized的话,打印出来的才

// 会有从大到小等的顺序等。

// 不然的话,打印出的内容等就会很乱,

// 这是安全性出了问题

synchronized (this) {

// synchronized关键字是用来控制线程同步的,

// 就是在多线程的环境下,

// 控制synchronized代码段不被多个线程同时执行。

//

// synchronized是Java中的关键字,是一种同步锁。

// 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()

    +"_____买的票数号码"+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();

  }

 }



}











创建一个兔子类,一个乌龟类,进行赛跑,目标为10米,

兔子每跑1米休息0.05秒,规定生成随机数,兔子生成的随机数范围为0-5,生成的随机数为3时才开始跑一米,乌龟生成的机数范围0-20,生成的随机数为13的时候才开始跑一米,乌龟每跑一米休息0.01秒 ,使用线程模拟这个特定龟兔赛跑的过程:




/**

 * 

 */

package thread;

import java.util.Random;

public class tuZi {

//垃圾回收线程:

// 执行垃圾回收的线程,称为垃圾回收线程。

public static void main(String[] args) throws Exception{


// 2.创建一个兔子类,一个乌龟类,进行赛跑,目标为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秒

//设置他们跑的速度就用随机数去设置

int shuzi=RandomNum.nextInt(25);

System.out.println("乌龟生成的随机数为"+shuzi);

//乌龟随机到13之后才开始跑

if(shuzi==13){

weiZhi++;//每次生成的随机数为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("兔子生成的随机数为了"+tuZiNum);

if(tuZiNum==3){

weiZhi++;//每次生成的随机数为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种状态组成:

1.就绪状态:实例化好了这个线程,但是并没有启动这个线程

2.可运行状态:启动了这个线程,但是这个线程并没有抢到cpu的使用权

3.运行状态:这个线程抢到了cpu的使用权

4.死亡状态:这个线程的代码全部执行完毕之后,就释放掉这个线程






//创建一个兔子类,一个乌龟类,进行赛跑,

//目标为100米,

//(1)兔子每 0.1 秒 5 米的速度,每跑20米休息0.1秒;

//(2)乌龟每 0.1 秒跑 2 米的速度,不休息,乌龟一直跑,使用线程模拟;





JS中回调函数(callback)理解:

字面上理解下来就是,回调就是一个函数的调用过程。那么就从理解这个调用过程开始吧。函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b。那么这个过程就叫回调。

其实中文也很好理解:回调,回调,就是回头调用的意思。函数a的事先干完,回头再调用函数b。

举个现实的例子:约会结束后你送你女朋友回家,离别时,你肯定会说:“到家了给我发条信息,我很担心你。”对不,然后你女朋友回家以后还真给你发了条信息。小伙子,你有戏了。

其实这就是一个回调的过程。你留了个函数b(要求女朋友给你发条信息)给你女朋友,然后你女朋友回家,回家的动作是函数a。她必须先回到家以后,函数a的内容执行完了,再执行函数b,然后你就收到一条信息了。

这里必须清楚一点:函数b是你以参数形式传给函数a的,那么函数b就叫回调函数。

 也许有人有疑问了:一定要以参数形式传过去吗,我不可以直接在函数a里面调用函数b吗?确实可以。求解中。

解惑:如果你直接在函数a里调用的话,那么这个回调函数就被限制死了。但是使用函数做参数就有下面的好处:当你a(b)的时候函数b就成了回调函数,而你还可以a(c)这个时候,函数c就成了回调函数。如果你写成了function a(){...;b();}就失去了变量的灵活性。



含个人的超级详细的解析:


//创建一个兔子类,一个乌龟类,进行赛跑,

//目标为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();

        // 回调方法的使用,谁先调用calltoback方法,另一个就不跑了

        

//        回调就是一个函数的调用过程。"call to back":"叫其回来"

//        那么就从理解这个调用过程开始吧。

//        函数a有一个参数,这个参数是个函数b,

//        当函数a执行完以后执行函数b。

//        那么这个过程就叫回调。   

//        LetLoserStop:让败者停止线程的开启   

        

        

//      当wuGuiDeClass wuGuiDeClass = new wuGuiDeClass();

//      部分的线程先结束(乌龟赢)时,

//        就会wuGuiDeClass传值

//        到回执函数,就会执行下面的一句的回执函数等,

//        calltoback != null,

//        就会执行乌龟类中的 calltoback.win();

//        让兔子类的也再次执行一次回执函数,让兔子停止

      

        LetLoserStop letLoserStopWuGui =

        new LetLoserStop(wuGuiDeClass);

        // 让兔子的回调方法里面存在乌龟对象的值,可以把乌龟停止stop:

        rabbitClass.calltoback = 

        letLoserStopWuGui;

        

        

        LetLoserStop letLoserStopRabbit =

        new LetLoserStop(rabbitClass);

        // 让乌龟的回调方法里面存在兔子对象的值,可以把兔子停止stop:

        wuGuiDeClass.calltoback = letLoserStopRabbit;

        // 开始跑:

        wuGuiDeClass.start();

        rabbitClass.start();


}

}


//LetOneStop:让一个停止


//当有一个到达终点的时候,需要让没到终点的乌龟或兔子的线程停止

//,不然的话就会有这里"乌龟获得了胜利"和

//"兔子获得了胜利"都打印出来,所以要用回调函数

//Calltoback,当兔子和乌龟的线程执行时,有一方到达时候,就把

//这一方的参数传到回调函数,让回调函数中声明的stop方法起效果


class LetLoserStop implements Calltoback {

    // 动物对象

    Animal loserClass;

 

    // 获取动物对象,可以传入兔子或乌龟的实例

    public LetLoserStop(Animal loserClass) {

        this.loserClass = loserClass;

    }

 

    // 让动物的线程停止:

    public void win() {

        // 线程停止用stop方法:

        loserClass.stop();

    }

}

class wuGuiDeClass extends Animal {

    public wuGuiDeClass() {

        setName("乌龟");// Thread的方法,给线程赋值名字

    }

 

    // 重写running方法,编写乌龟的奔跑操作

    @Override

    public void runing() {

        // x:乌龟的位移:

        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实现速度的效果

        } 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("兔子获得了胜利");

            // 给回调对象赋值,让乌龟不要再跑了

            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();

        }

    }

 

}


//这里用动物类继承了线程类就

//可以有线程类等的特性等,在主函数传兔子类或乌龟类时,就不会报错等

abstract class Animal extends Thread {

    public int length = 100;// 比赛长度

 

    public abstract void runing();

 

    @Override

    public void run() {

        super.run();

        while (length > 0) {

            runing();

        }

    }

 

    // 在需要回调数据的地方(两个子类需要),声明一个接口

    public static interface Calltoback {

        public void win();

    }

 

    // 2.创建接口对象

    public Calltoback calltoback;

 

}











创建一个人物类,创建人物张三和李四共同去挖矿,用一个数字5代表金矿,声明随机数,当挖到金矿的时候,当前线程打印“呵呵,挖到金矿了”并且礼让线程,一共挖30次金矿,统计每个人挖到金矿的次数。



/**

 * 

 */

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("生成的随机数为"+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()+"抢到当前CPU,现在挖到的金矿次数为"+num+"次");

// 个人理解:礼让就是选择放弃独占CPU,

// 选择和其他线程分享抢到的CPU

if(num%5==0){

Thread.yield();

// yield 英[jiːld]

// 美[jiːld]

// v. 出产(作物); 产生(收益、效益等);

// 提供; 屈服; 让步; 放弃; 缴出;

// 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;

}

}

}

}

}










个人对守护线程的理解:



Java车票,车站,生命周期,龟兔赛跑,同步锁,礼让,守护线程,挖金矿【诗书画唱】的评论 (共 条)

分享到微博请遵守国家法律