用JAVA多线程实现龟兔赛跑

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用JAVA多线程实现龟兔赛跑相关的知识,希望对你有一定的参考价值。

创建两个线程,实现龟兔赛跑,线程每次执行休眠500毫秒,两个线程每次分别执行乌龟前行10米与兔子前行10米。一方先到100米处结束程序,显示获胜信息。
本人初学,请用大家写的简单易懂一点,谢谢!!
分不够多,请大家帮帮忙!!

参考技术A 程序如下:

/**
*
* GuiTuSaiPao.java
* @author Antonio
* 2009年9月2日20:16:33
* 实现Runnable接口中的run方法
*
*/
public class GuiTuSaiPao implements Runnable
private String name;
private int length=0;

public GuiTuSaiPao()

public GuiTuSaiPao(String name)
this.name=name;


public void run()
while(true)
//每次停500毫秒
try
Thread.sleep(500);
catch (InterruptedException e)
e.printStackTrace();

//向前跑十米
length+=10;
System.out.println(name+"已跑了"+length+"米.");
//到达终点
if(length>=100)
System.out.println(name+",已经到达终点!");
//结束赛跑,break
break;




public static void main(String[] args)
GuiTuSaiPao wugui=new GuiTuSaiPao("乌龟");
GuiTuSaiPao tuzi=new GuiTuSaiPao("兔子");
Thread thread=new Thread(wugui);
Thread thread2=new Thread(tuzi);
//启动线程
thread.start();
thread2.start();





输出结果:(不一定每次都一样!)
乌龟已跑了10米.
兔子已跑了10米.
兔子已跑了20米.
乌龟已跑了20米.
乌龟已跑了30米.
兔子已跑了30米.
兔子已跑了40米.
乌龟已跑了40米.
兔子已跑了50米.
乌龟已跑了50米.
乌龟已跑了60米.
兔子已跑了60米.
乌龟已跑了70米.
兔子已跑了70米.
乌龟已跑了80米.
兔子已跑了80米.
兔子已跑了90米.
乌龟已跑了90米.
兔子已跑了100米.
兔子,已经到达终点!
乌龟已跑了100米.
乌龟,已经到达终点!

完全看rp,这就是线程!

给分吧,哈哈本回答被提问者采纳
参考技术B package test;

public class RunningGame

public static void main(String[] args)

Runner wugui = new Runner("wugui");
Runner tuzi = new Runner("tuzi");

//为增加趣味性,可用重载的构造函数,初始化各项数据,这样兔子睡觉时间比较多,但速度比较快,胜负难料

// Runner wugui = new Runner("wugui",500,10);
// Runner tuzi = new Runner("tuzi",1200,25);

wugui.start();
tuzi.start();




class Runner extends Thread
private static final int LENGTH = 100; //总路程
private String name; //名字
private int sleep = 500; //睡觉时间
private int speed = 10; //速度
private int meter = 0; //当前路程

public Runner(String name)

this.name = name;


public Runner(String name, int sleep)

this.name = name;
this.sleep = sleep;

public Runner(String name, int sleep, int speed)

this.name = name;
this.sleep = sleep;
this.speed = speed;


public void run()

while(meter < LENGTH)
try
Thread.sleep(sleep);
catch (InterruptedException e)

e.printStackTrace();

meter += speed;
System.out.println(name+":" + meter + " meters");


System.out.println(name + " win the game");
System.exit(0);



参考技术C 兄弟??
还要写个程序给你??
最多是给你点提示罢了....

狂神说Java笔记--多线程详解部分笔记


传送门==>B站遇见狂神说Java多线程详解

做笔记时有的知识点并没有整理;


1.线程创建之继承Thread类

  • 首先自定义线程类继承Thread类;
  • 然后是重写run( )方法;编写线程执行体
  • 然后创建自定义线程对象;使用start()方法启动线程

注意:线程开启并不一定是直接就执行;得看CPU的调度,或者说的根据CPU的实际资源情况;

代码练习:
创建MyThread

/**
 * 线程创建之继承Thread类;
 */
//1.首先继承Thread类;
public class MyThread01 extends Thread {
    //2.然后是重写run方法;编写执行的线程;
    @Override
    public void run() {
        //run方法 线程的执行体;
        for (int i = 0; i < 100; i++) {
            System.out.println("我是run方法->"+i);
        }
    }

    //mian方法;(主线程)
    public static void main(String[] args) {
        //创建线程对象;
        MyThread01 myThread01=new MyThread01();
        //3.使用start方法启动线程;
        myThread01.start();

        //main方法 线程的执行体;
        for (int i = 0; i < 100; i++) {
            System.out.println("我是main方法->"+i);
        }
    }
}

线程交替执行

而如果不使用start方法启动线程呢;直接在main方法中调用run方法;那就按着方法的调用顺序执行了,依次有序地执行


图片下载练习

//继承Thread类;
public class MyThread02 extends Thread{
    //定义网页地址和文件名;
    private String url;
    private String name;
    //构造方法;初始化;
    public MyThread02(String url, String name) {
        this.url = url;
        this.name = name;
    }

    //重写run方法
    @Override
    public void run() {
        //创建下载器对象;
        WebDownLoader wdl=new WebDownLoader();
        //调用下载方法;
        wdl.dowLoade(url,name);
        System.out.println("下载文件名=>"+name);
    }

    //主方法;
    public static void main(String[] args) {
        MyThread02 myT1=new MyThread02("https://www.baidu.com/link?url=dvRgPF9UDWw42jQF0lr8EnKMw2XfU_NKhWqanB4wL85sqwWrGBVnBAGd3zBJUJ0JZa0d3ryBEd6FCiZfrG1ax0o3EkygROiBPwUrzEFRoC4DK6S5DSiMz1Q1Ge_O8vyNbE8IzW1Kn2WGbHDgGzx4yhlQsOadV1rFqemy4Os4lhBMAxGLXZ2CY5ftLFMYzxUgZbFIw5qtkPUajas-nPD4yyk118flZrp6Dj6HOAfwKB-X0xbxH2ttXMocCGzVHuwGm0a0Orw8A_cqyOm3tDvXMhKu3YSYHtKDkisZqupVBI3pJhhvP97RCXacC0jtynAXvUrPz4OAhT_QvMfWp7akjFP5gBFiK_5Tt2BwRchJ1YgenbZwqGucGAopjBtmlKeAKOmkaVJ12wiG6u7Y85YNIlGo__O0ZgurYtRb4WbOZTxsBX_e0XrBB0klH2V2BJM3YuEyMpc_6sZdwhYnj4JCltSh1oca5jDlQ51Tu2LHqI-SeDhvi_ioBAno4NzkQqEI_rhRIJSUqb7EVBjO7sTEB8qohgcbM9ZtD-3fqTYTRZBQ97W0o5p2tUTEVuXDTM0FeunmEEoiaLeBCSJbB8to09OYCCy9C-e2CZyaaiIAnXvAlAILYMaHh0a1ANXLzFR1&wd=&eqid=9a0261300016198200000005611d721a","图1.jpg");
        MyThread02 myT2=new MyThread02("https://www.baidu.com/link?url=dvRgPF9UDWw42jQF0lr8EnKMw2XfU_NKhWqanB4wL85sqwWrGBVnBAGd3zBJUJ0JZa0d3ryBEd6FCiZfrG1ax0o3EkygROiBPwUrzEFRoC4DK6S5DSiMz1Q1Ge_O8vyNbE8IzW1Kn2WGbHDgGzx4yhlQsOadV1rFqemy4Os4lhBMAxGLXZ2CY5ftLFMYzxUgZbFIw5qtkPUajas-nPD4yyk118flZrp6Dj6HOAfwKB-X0xbxH2ttXMocCGzVHuwGm0a0Orw8A_cqyOm3tDvXMhKu3YSYHtKDkisZqupVBI3pJhhvP97RCXacC0jtynAXvUrPz4OAhT_QvMfWp7akjFP5gBFiK_5Tt2BwRchJ1YgenbZwqGucGAopjBtmlKeAKOmkaVJ12wiG6u7Y85YNIlGo__O0ZgurYtRb4WbOZTxsBX_e0XrBB0klH2V2BJM3YuEyMpc_6sZdwhYnj4JCltSh1oca5jDlQ51Tu2LHqI-SeDhvi_ioBAno4NzkQqEI_rhRIJSUqb7EVBjO7sTEB8qohgcbM9ZtD-3fqTYTRZBQ97W0o5p2tUTEVuXDTM0FeunmEEoiaLeBCSJbB8to09OYCCy9C-e2CZyaaiIAnXvAlAILYMaHh0a1ANXLzFR1&wd=&eqid=9a0261300016198200000005611d721a","图2.jpg");
        MyThread02 myT3=new MyThread02("https://www.baidu.com/link?url=dvRgPF9UDWw42jQF0lr8EnKMw2XfU_NKhWqanB4wL85sqwWrGBVnBAGd3zBJUJ0JZa0d3ryBEd6FCiZfrG1ax0o3EkygROiBPwUrzEFRoC4DK6S5DSiMz1Q1Ge_O8vyNbE8IzW1Kn2WGbHDgGzx4yhlQsOadV1rFqemy4Os4lhBMAxGLXZ2CY5ftLFMYzxUgZbFIw5qtkPUajas-nPD4yyk118flZrp6Dj6HOAfwKB-X0xbxH2ttXMocCGzVHuwGm0a0Orw8A_cqyOm3tDvXMhKu3YSYHtKDkisZqupVBI3pJhhvP97RCXacC0jtynAXvUrPz4OAhT_QvMfWp7akjFP5gBFiK_5Tt2BwRchJ1YgenbZwqGucGAopjBtmlKeAKOmkaVJ12wiG6u7Y85YNIlGo__O0ZgurYtRb4WbOZTxsBX_e0XrBB0klH2V2BJM3YuEyMpc_6sZdwhYnj4JCltSh1oca5jDlQ51Tu2LHqI-SeDhvi_ioBAno4NzkQqEI_rhRIJSUqb7EVBjO7sTEB8qohgcbM9ZtD-3fqTYTRZBQ97W0o5p2tUTEVuXDTM0FeunmEEoiaLeBCSJbB8to09OYCCy9C-e2CZyaaiIAnXvAlAILYMaHh0a1ANXLzFR1&wd=&eqid=9a0261300016198200000005611d721a","图3.jpg");
        //启动线程;
        myT1.start();
        myT2.start();
        myT3.start();
    }
}

//创建下载器;
class WebDownLoader{
    //下载方法;
    public void dowLoade(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("下载方法有问题, IO异常");
        }
    }
}

运行;下载时并不会按照顺序,


2.线程创建之实现Runnable接口

可避免单继承的局限性;方便一个对象被多个线程使用.

  • 自定义类实现Runnable接口;
  • 重写run()方法,编写线程执行体
  • 创建自定义线程对象放入Thread对象中,start()方法启动线程

代码练习

/**
 * 创建线程之实现Runnable接口
 */
//实现Runnable接口;
public class MyThread03 implements Runnable {

    //重写run方法;
    @Override
    public void run() {
        //run方法 线程的执行体;
        for (int i = 0; i < 100; i++) {
            System.out.println("我是run方法->" + i);
        }
    }

    //主方法;
    public static void main(String[] args) {
        //创建实现类的对象;
        MyThread03 myThread03 = new MyThread03();
        //创建线程对象;启动线程
        new Thread(myThread03).start();

    //main方法 线程的执行体;
        for (int i = 0; i < 100; i++) {
            System.out.println("我是main方法->" + i);
        }
    }
}

买票案例

多个线程去操作同一份资源,线程不安全

//实现Runnable接口;
public class MyThreadToTicket implements Runnable {
    //定义车票数量;
    private int ticket=10;
    //重写run方法;
    @Override
    public void run() {
        while(true) {
            //票买完就停了;
           if(ticket<=0) {
                break;
            }

            try {
                //定义延时;
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //Thread.currentThread().getName():可获取到当前线程的名字;
            System.out.println(Thread.currentThread().getName() + "::买到了第" + ticket-- + "个票");
        }
    }
    //主方法;
    public static void main(String[] args) {
        //创建自定义类的对象;
        MyThreadToTicket mt=new MyThreadToTicket();
        //创建Thread对象,启动线程;
        new Thread(mt,"阿杰").start();
        new Thread(mt,"阿猫").start();
        new Thread(mt,"阿伟").start();
    }
}

运行时,出现两个人买到同一张票的问题.


模拟龟兔赛跑

//实现Runnable接口;
public class TorAndRabRun implements Runnable {
    //定义胜利者;
    private static String win;

    //判断是否结束比赛; step:步数;
    private boolean over(int step){
        //若已有获胜者,则结束;
        if(win!=null){
            return true;
        }{
            //若已经跑完了,结束比赛;
            if(step>=100){
                win=Thread.currentThread().getName();
                System.out.println("获胜者" + win);
                return true;
            }
        }
        return false;
    }

    //重写run方法
    @Override
    public void run() {
        for (int i = 0; i <= 101; i++) {
            //模拟兔子睡觉;
            if(Thread.currentThread().getName().equals("兔纸")&&i%10==0){
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //若比赛结束,终止循环;
            if (over(i)) {
                break;
            }
            //Thread.currentThread().getName():会获取线程名;
            System.out.println(Thread.currentThread().getName()+"==>跑"+i+"米");
        }
    }
    //主方法;
    public static void main(String[] args) {
        //创建赛道对象;
        TorAndRabRun tar=new TorAndRabRun();

        //创建线程对象,启动线程;
        new Thread(tar,"乌龟").start();
        new Thread(tar,"兔纸").start();
    }
}


3.线程创建之实现Callable接口

  • 实现callable接口,需要返回值类型;
  • 重写call方法;需要抛出异常类型;
  • 创建自定义线程的对象;
  • 开启服务;
  • 提交执行;
  • 获取结果;
  • 关闭服务

使用之前的多线程下载图片案例;

/**
 * 线程创建之实现Callable接口;和前两种不同的是该方式可产生返回值;
 */
//实现Callable接口;
public class MyThread04 implements Callable<Boolean> {
    //定义网页地址和文件名;
    private String url;
    private String name;
    //构造方法;初始化;
    public MyThread04(String url, String name) {
        this.url = url;
        this.name = name;
    }

    //重写callable方法;
    @Override
    public Boolean call() throws Exception {
        //创建下载器对象;
       WebDownLoader wdl=new WebDownLoader();
        //调用下载方法;
        wdl.dowLoade(url,name);
        System.out.println("下载文件名=>"+name);
        return null;
    }

    //主方法
    public static void main(String[] args) throws ExecutionException, InterruptedException{
        //创建实现类的对象;
        MyThread04 myT1=new MyThread04("https://img-blog.csdnimg.cn/20210613214620230.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L01yVHVtbnVz,size_16,color_FFFFFF,t_70","图片1.png");
        MyThread04 myT2=new MyThread04("https://img-blog.csdnimg.cn/20210613214620230.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L01yVHVtbnVz,size_16,color_FFFFFF,t_70","图片2.png");
        MyThread04 myT3=new MyThread04("https://img-blog.csdnimg.cn/20210613214620230.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L01yVHVtbnVz,size_16,color_FFFFFF,t_70","图片3.png");

        //开启服务;(创建线程池)
        ExecutorService es= Executors.newFixedThreadPool(3);
        //执行服务提交;
        Future<Boolean> ft1=es.submit(myT1);
        Future<Boolean> ft2=es.submit(myT2);
        Future<Boolean> ft3=es.submit(myT3);
        //获取返回结果;
        Boolean res1 = ft1.get();
        Boolean res2 = ft2.get();
        Boolean res3 = ft3.get();
        System.out.print(res1);
        System.out.print(res2);
        System.out.print(res3);
        //关闭服务;
        es.shutdownNow();
    }
}
//创建下载器;
class WebDownLoader{
    //下载方法;
    public void dowLoade(String url,String name){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("下载方法有问题, IO异常");
        }
    }
}

也是交替执行的;


4.静态代理模式

  • 真实对象(目标对象)和代理对象都要实现同一个接口;
  • 代理对象要代理真实角色;
  • 代理对象可实现真实对象不能完成的方法;
  • 真实对象专注自己的实现;
public class StaticProxy {
    public static void main(String[] args) {
        //代理        |  真实       |             需要完成的事情;
        //new Thread(()->System.out.println("完成")).start();

       /* //创建真实角色对象;
        Person ps=new Person();
        //创建代理角色对象;
        ProxyPerson prop=new ProxyPerson(ps);
        prop.Happy();*/

        //实际上,可精简为;
        //      代理    |  真实    |  需要完成的事情;
        new ProxyPerson(new Person()).Happy();
    }
}

//接口;
interface Marry{
    //抽象方法;
    void Happy();
}

//人;(真实角色)
class Person implements  Marry{

    @Override
    public void Happy() {
        System.out.println("真实角色出场");
    }
}

//中介;(代理角色)
class ProxyPerson implements Marry{
    //定义目标对象1;
    private Marry targetP;
    //构造方法;
    public ProxyPerson(Marry targetP) {
        this.targetP = targetP;
    }

    @Override
    public void Happy() {
        //调用之前要完成的方法;
        brfore();
        //执行方法;
        this.targetP.Happy();
        //调用之后要完成的方法
        after();
    }

    //之前要进行的方法;
    private void brfore() {
        System.out.println("前面要完成的事情;");
    }
    //之后要进行的方法;
    private void after() {
        System.out.println("后面要完成的事情;");
    }
}

5.Lambda表达式

lambda:
λ:希腊字母表第11;
使用目的是为了避免匿名内部类定义过多;实质上属于函数式编程;
-----------------------------------
(params)->expression [表达式]
(params)->statement (语句)
-----------------------------------
函数式接口:(Functional Interface)
----------------------------------
函数式接口定义:
只包含唯一的抽象方法;
可使用lambda表达式创建接口对象

练习;使用不同的方式实现输出接口方法;

public class DemoLamDa01 {
    //2.使用静态内部类;
    static class FunImpl02 implements FunMeth{
        @Override
        public void OnlyMethod以上是关于用JAVA多线程实现龟兔赛跑的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程模拟龟兔赛跑

java——多线程的实现方式两种办法解决线程赛跑

第70题JAVA高级技术-多线程4(龟兔赛跑-休眠线程)

第70题JAVA高级技术-多线程4(龟兔赛跑-休眠线程)

狂神说Java笔记--多线程详解部分笔记

Java多线程 模拟龟兔赛跑