• 多线程


    线程

    1.多线程的介绍

    进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。

    线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

    什么是多线程呢?即就是一个程序中有多个线程在同时执行。

    2.程序运行原理

    分时调度

    所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

    抢占式调度

    优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。

    实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而 CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。

    3.创建多线程

    创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
    public class TestThread1 extends Thread{
       @Override
       public void run() {
           //run方法线程体
           for (int i=0;i<20;i++){
               System.out.println("我在看代码"+i);
          }
      }

       public static void main(String[] args) {
           //创建一个线程对象
           TestThread1 ts=new TestThread1();
           //调用start方法
           ts.start();

           //main线程,主线程
           for (int i=0;i<200;i++){
               System.out.println("我在看线程"+i);
          }
      }
    }

     

    //创建线程方式二:实现runnable接口,重写run方法,执行线程需要丢入rnunable接口实现,调用start方法
    public class TestThread3 implements Runnable{
       @Override
       public void run() {
           //run方法线程体
           for (int i=0;i<200;i++){
               System.out.println("我在看代码"+i);
          }
      }

       public static void main(String[] args) {
          //创建Rnunable接口的实现类对象
           TestThread3 testThread3=new TestThread3();
           new Thread(testThread3).start();

           //main线程,主线程
           for (int i=0;i<200;i++){
               System.out.println("我在看线程"+i);
          }
      }
    }

    对比:

    继承Thread类

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

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

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

    实现Runnable接口

    实现接口Runnable具有多线程功能

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

    推荐使用:避免单继承的局限性,灵活方便

     

    4.继承Thread类原理

    我们为什么要继承Thread类,并调用其的start方法才能开启线程呢?

    继承Thread类:因为Thread类用来描述线程,具备线程应该有功能。那为什么不直接创建Thread类的对象呢?如下代码:

    Thread t1 = new Thread();

    t1.start();//这样做没有错,但是该start调用的是Thread类中的run方法,而这个run方法没有做什么事情,更重要的是这个run方法中并没有定义我们需要让线程执行的代码。

    创建线程的目的是什么?

    是为了建立程序单独的执行路径,让多部分代码实现同时执行。也就是说线程创建并执行需要给定线程要执行的任务。

    对于之前所讲的主线程,它的任务定义在main函数中。自定义线程需要执行的任务都定义在run方法中。

    Thread类run方法中的任务并不是我们所需要的,只有重写这个run方法。既然Thread类已经定义了线程任务的编写位置(run方法),那么只要在编写位置(run方法)中定义任务代码即可。所以进行了重写run方法动作。

    5.获取线程名称

    Thread.currentThread()获取当前线程对象

    Thread.currentThread().getName();获取当前线程对象的名称

     

    6.Lambda表达式

    package com.dabai.Demo02;

    //lambda总结
    //1.lambda表达式只能有一行代码的情况下才能简化成为一行代码,如果有多行,就要用代码快包裹
    //2.前提是接口为函数式接口(就是只有一个抽象方法的接口)
    //3.多个参数也可以去掉参数类型,要去掉就都去掉,必须加上括号


    //推导lambda表达式
    public class TestLambda1 {


      //3.静态内部类
      static class Like2 implements Ilike{
          @Override
          public void lambda() {
              System.out.println("i like lambda2");
          }
      }


      public static void main(String[] args) {
          Ilike like=new Like();
          like.lambda();

          like =new Like2();
          like.lambda();


          //4.局部内部类 (在mian方法体中)
          class Like3 implements Ilike{
              @Override
              public void lambda() {
                  System.out.println("i like lambda3");
              }
          }
          like =new Like3();
          like.lambda();

          //5.匿名内部类,没有类的名称,必须借助接口或者父类
          like=new Ilike() {
              @Override
              public void lambda() {
                  System.out.println("i like lambda4");
              }
          };
          like.lambda();

          //6.用lambda简化
          like= ()->{
              System.out.println("i like lambda5");
          };
          like.lambda();
      }
    }

    //1.定义一个函数式接口(只有一个抽象方法)
    interface Ilike{
      void lambda();
    }

    //2.实现类
    class Like implements Ilike{
      @Override
      public void lambda() {
          System.out.println("i like lambda");
      }
    }

     

    7.线程状态

     

    image-20200228135556980

     

    8.线程方法

    image-20200228135827215

    image-20200228140222932

    image-20200228140248197

     

    9.线程同步

    image-20200228140623364

    image-20200228140700474

    package com.kuang.syn;

    //不安全的买票
    //线程不安全,有负数
    public class UnsafeBuyTicket {
      public static void main(String[] args) {
          BuyTicket station=new BuyTicket();

          new Thread(station,"aa").start();
          new Thread(station,"bb").start();
          new Thread(station,"xx").start();
      }

    }

    class BuyTicket implements Runnable{

      //票
      private int ticketNums=10;
      boolean flag=true;//外部停止方式
      @Override
      public void run() {
          //买票
          while (flag){
              try {
                  buy();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      }

      //synchronized 同步方法,锁的是this
      private synchronized void buy() throws InterruptedException {
          //判断是否有票
          if(ticketNums<=0){
              flag=false;
              return;
          }

          //模拟延时
          Thread.sleep(100);
          //买票
          System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
      }
    }
  • 相关阅读:
    完全背包详解
    0-1背包详解
    优先队列 + 模拟
    循环节 + 矩阵快速幂
    并查集 + 路径压缩(经典) UVALive 3027 Corporative Network
    dp
    动态规划分类(完整版)
    (二)Spring框架之JDBC的基本使用(p6spy插件的使用)
    (一)Spring框架基础
    (十六)客户端验证与struts2中的服务器端验证
  • 原文地址:https://www.cnblogs.com/dadabai/p/12377007.html
Copyright © 2020-2023  润新知