2022/10/12线程核心概念

线程核心概念

  • 线程就是独立的执行路径。

  • 在程序运行时,即使自己没有创建线程,后台也会有多个线程,如主线程,gc线程。

  • main()称之为主线程,为系统的入口,用于执行整个程序。

  • 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能人为干预的

  • 对同一份资源操作时,会存在资源抢夺的问题需要加入并发控制。

  • 对同一份资源操作时,会存在资源抢夺问题,需要加入并发控制。

  • 线程会带来额外的开销,如cpu调度时间,并发控制开销。

  • 每个线程在自己的工作内存交互,内存控制不当造成数据不一致。

三种创建方式

  • Thread class:继承Thread类(重点)

  • Runnable接口:实现Runnable接口(重点)

  • Callable接口:实现Callable接口(了解)

Thread

  • 自定义线程类继承Thread类

  • 重写run()方法,编写线程执行体

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

public class TestThread1 extends Thread{
   @Override
   public void run() {
       super.run();
       //run放方法线程体
       for (int i = 0; i < 20; i++) {
           System.out.println("我在看代码"+i);
      }

  }

   public static void main(String[] args) {
       //main线程,主线程
       //创建一个线程对象
       TestThread1 testThread1 = new TestThread1();
       //new一个线程对象
       testThread1.start();//调用start方法,开启线程
       for (int i = 0; i < 20; i++) {
           System.out.println("我在学习多线程"+i);

      }
  }
}

 

 

 

public  class TestThread2 extends Thread{
  private String url;
  private String name;
  public TestThread2(String url,String name){
      this.url=url;
      this.name=name;
  }
  @Override
  public void run() {
      WebDownLoader webDownLoader = new WebDownLoader();
      webDownLoader.downloader(url,name);
      System.out.println("下载文件图片名为:"+name);
  }

  public static void main(String[] args) {
      TestThread2 t1=new TestThread2("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F010421143P0%2F210104143P0-4-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668094322&t=1222fed63d4d2315eb80ed377579ec90","1.jpg");
      TestThread2 t2=new TestThread2("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F010421143P0%2F210104143P0-4-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668094322&t=1222fed63d4d2315eb80ed377579ec90","2.jpg");
      TestThread2 t3=new TestThread2("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Flmg.jj20.com%2Fup%2Fallimg%2F1114%2F010421143P0%2F210104143P0-4-1200.jpg&refer=http%3A%2F%2Flmg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668094322&t=1222fed63d4d2315eb80ed377579ec90","3.jpg");
  t1.start();
  t2.start();
  t3.start();
  }
}
//下载器
class WebDownLoader{
  public void downloader (String url,String name){
      try {
          FileUtils.copyURLToFile(new URL(url),new File(name));
      } catch (IOException e) {
          throw new RuntimeException(e);
      }
  }
  }

Runnable

  • 定义MyRunnable类实现Runnable接口

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

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

小结

  • 继承Thread类

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

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

    • 不建议使用:避免oop单继承局限性

  • 实现Runnable接口

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

    • 启动线程:传入目标对象+Thread(对象).start()

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

//多个线程同时操作一个对象
//买火车票的例子
//发现问题:多个线程操作同一个资源时,线程不安全,数据紊乱。
public class TestThread4 implements Runnable{
   private int ticketNums = 10;
   @Override
   public void run() {
       while (true){
           if (ticketNums<0){
               break;
          }
           try {
               Thread.sleep(200);
          } catch (InterruptedException e) {
               throw new RuntimeException(e);
          }
           System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNums--+"票");
      }
  }

   public static void main(String[] args) {
       TestThread4 ticket = new TestThread4();
       new Thread(ticket,"小明").start();
       new Thread(ticket,"小红").start();
       new Thread(ticket,"小颜").start();
  }
}

案例

龟兔赛跑

image-20221012003831034

public class Race implements Runnable{
   //胜利者
   public static String winner;
   @Override
   public void run() {
       for (int i = 0; i <=100; i++) {
           //模拟兔子休息
           if (Thread.currentThread().getName().equals("兔子")&&i%10==0){
               try {
                   Thread.sleep(10);
              } catch (InterruptedException e) {
                   throw new RuntimeException(e);
              }
          }
           //判断比赛是否结束
           boolean flag = gameOver(i);
           //如果比赛结束了,停止程序
           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();
       System.out.println("");
  }
}
 
posted @   yan三水  阅读(147)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示