Java的Run/Callable实现

实现Runnable

  • 学习提示:查看JDK帮助文档

  • 定义 MyRunnable 类实现 Runnable 接口

  • 实现 run() 方法,编写线程执行体。

  • 创建线程对象,调用 start() 方法启动线程。

public class StartThread implements Runnable{
   @Override
   public void run(){
       //线程体
       for (int i=0; i < 20; i++){
           System.out.println("我在玩泥巴====");
      }
  }
}

//创建实现类对象
StartThread st = new StartThread();
//创建代理类对象
Thread thread = new Thread(st);
//启动
thread.start();
  • 推荐使用Runnable对象,因为Java单继承的局限性。

package com.kuang.demo;
//创建线程方法二:实现runnable接口,重写run方法,执行线程需要丢入runnable接口的实现类,调用start方法。
public class TestThread implements Runnable{
   @Override
   public  void run(){
       //run方法线程体
       for (int i=0; i < 200; i++){
           System.out.println("lisening:" + i);
      }
  }
   
   public static void main(String[] args){
       //创建runnable接口的实现类对象
       TestThread testThread = new TestThread();
       //创建线程对象,通过线程对象来开启我们的线程,称作代理。
       Thread thread = new Thread(testThread);
       thread.start();
       //new Thread(testThread).start();
       
       for (int i=0; i < 1000; i++){
           System.out.println("watching:" + i)
      }
  }
}

小结

  • 继承Thread类

    • 子类继承Thread类就具备了多线程能力

    • 启动线程:子类对象.start()

    • 不建议使用,避免面向对象的单继承局限性

  • 实现Runnable接口

    • 实现接口Runnable具有多线程能力

    • 启动线程:实例化目标对象 + Thread对象(目标对象).start()

    • 推荐使用:避免单继承局限性,极为灵活,方便同一个对象被多个线程使用。

//一份资源
StartThread station = new StartThread();
//多个代理,给线程起别名。
new Thread(station, "小明").start();
new Thread(station, "小红").start();
new Thread(station, "小兰").start();

多个线程同时操作同一个对象

package com.kuang.demo;
//多个线程同时操作同一个对象
//买火车票的例子
//发现问题:多个线程操作同一个资源的情况下,线程不安全了,数据紊乱。
public class TestThread implements Runnable{
   //火车票数量
   private int ticktNums = 10;
   
   @Override
   public void run(){
       while (true){
           if (ticktNums <= 0){
               break;
          }
           //模拟延时,让线程睡觉。
           try{
               Thread.sleep(200); //需要配套异常使用
          }catch(InterruptedException e){
               e.printStackTrace();
          }
           //Thread.currentThread().getName() 通过这个方法可以得到当前执行线程的名字
           System.out.println(Thread.currentThread().getName() + "get the" + ticketNums-- + "tickt");
      }
  }
   public static void main(String[] args){
       TestThread  ticket = new TestThread();
       //启用代理,给线程起别名。
       new Thread(ticket, "小明").start();
       new Thread(ticket, "小红").start();
       new Thread(ticket, "小兰").start();
  }
}
  • 案例:龟兔赛跑

    • 首先来个赛道距离,然后要离终点越来越近。

    • 判断比赛是否结束

    • 打印出胜利者

    • 龟兔赛跑开始

    • 故事里是乌龟赢,兔子要睡觉,我们需要模拟兔子睡觉

    • 最终乌龟赢得比赛

package com.kuang.demo;
//模拟龟兔赛跑
public class Race implements Runnable{
   //胜利者
   private static String winner;
   
   @Override
   public void run(){
       for (int i=0; i <= 10; i++){
           //模拟兔子休息
           if (Thread.currentThread().getName().equals("rabbit") && (i % 10 == 0)){
               try{
                   Thread.sleep(100);
              }catch(InterruptedException e){
                   e.printStackTrace();
              }
          }
           //判断比赛是否结束
           boolean flag = gameOver(i);
           //如果比赛结束了,就停止程序。
           if (flag){
               break;
          }
           System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
      }
  }
   
   //判断是否完成比赛
   private boolean gemeOver(int steps){
       
  }
   public static void main(String[] args){
       //判断是否有胜利者
       if (winner != null){
           //已经存在胜利者
           return true;
      }{
           if (step >= 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, "rabbit").start();
       new Thread(race, "tortoise").start()
  }
}

实现callable接口(了解)

  • 实现callable接口,需要返回值类型。

  • 重写call方法,需要抛出异常。

  • 创建目标对象

  • 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);

  • 提交执行:Future<Boolean>result1 = ser.submit(t1);

  • 获取结果:boolean r1 = result1.get()

  • 关闭服务:ser.shuntdownNow();

package com.kuang.demo;
//线程创建方式三:实现callable接口
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
//线程实现方式三:实现callable接口。

/** callable的好处
* 1、可以定义返回值
* 2、可以抛出异常
*/
public class TestCallable implements Callable<Boolean>{
   private String url; //网络图片地址
   private String name; //保存的文件名
   
   public TestCallable(String url, String name){
       this.url = url;
       this.name = name;
  }
   
   //下载图片的线程执行体
   @Override
   public Boolean call(){
       WebDownloader webDownloader = new WebDownloader();
       WebDownloader.downloader(url, name);
       System.out.println("下载文件名为:" + name);
       return true;
  }
   
   public static void main(String[] args) throws ExecutionException, InterruptedException{
       TestCallable t1 = new TestCallable("https://blog.kuangstudy.com/...", "why1.jpg");
       TestCallable t2 = new TestCallable("https://blog.kuangstudy.com/...", "why2.jpg");
       TestCallable t3 = new TestCallable("https://blog.kuangstudy.com/...", "why3.jpg");
       
       // 创建执行服务,即开启一个服务。
       ExecutorService ser = Executors.newFixedThreadPool(3);
       // 提交执行,和start线程一样。
       Future<Boolean> result1 = ser.submit(t1);
       Future<Boolean> result2 = ser.submit(t2);
       Future<Boolean> result3 = ser.submit(t3);
       //获取结果,即call方法返回的结果。
       boolean r1 = result1.get();
       boolean r2 = result2.get();
       boolean r3 = result3.get();
       
       System.out.println(r1);
       System.out.println(r2);
       System.out.println(r3);
       //关闭服务:
       ser.shutdownNow();
  }
}

 

posted on 2021-11-10 21:17  愿将过往均储藏  阅读(98)  评论(0)    收藏  举报

导航