首页 > 编程语言 >Java多线程学习笔记

Java多线程学习笔记

时间:2022-12-04 22:58:52浏览次数:46  
标签:Java Thread 笔记 start static 线程 new 多线程 public

程序、进程、线程

  程序:是为了完成特定任务,用某种语言编写的一组指令的集合,是一段静态的代码。(程序是静态的)
  进程:是程序的一次动态执行。正在运行的一个程序,进程作为资源分配的单位,在内存中会为每个进程分配不同的内存区域。(进程是动态的),进程的生命周期:有它自身的产生、存在和消亡的过程。
  线程:进程可进一步细化为线程,是一个程序内部的一条执行路径。若一个进程同一时间并行执行多个线程,就是支持多线程的。

单核CPU与多核CPU

  单核CPU:CPU在执行的时候,是按照时间片执行的,同一个时间片只能执行一个任务。执行多个任务时,会在多个任务之间来回跳。时间片切换很快,给人感觉像是在同时执行多个线程。是一种假象。
  多核CPU:多个CPU的时候,才真正意义上做到一个时间片多线程同时执行。多线程发挥了最好的效率。真正的多线程。

并行和并发

  并行:多个CPU同时执行多个任务。
  并发:一个CPU“同时”执行多个任务。(采用时间片切换)

在学习多线程之前,以前的代码都是单线程吗?

  不是,以前的代码也是多线程。除了main方法为主线程,还包括处理异常的线程和垃圾回收的线程。PS:处理异常的线程会影响主线程的执行。

创建线程的三种方式

1. 继承Thread类
    public class BuyTicketThread extends Thread{
        public BuyTicketThread(String name){
          super(name);
        }
        //一共10张票
        static int ticketNum = 10;//加上static,使得票数被三个线程共享,否则会售出30张票

        @Override
        public void run(){
            //每个窗口后面有100个人在抢票
            for (int i = 1; i <= 100; i++) {
                //票数大于0才售票
                if (ticketNum>0){
                    System.out.println("我在"+this.getName()+"抢到了从北京到邯郸的第"+ ticketNum-- +"张票");
                }

            }
        }
    }

    public class Test {
        public static void main(String[] args) {
            //多个窗口抢票
            BuyTicketThread buy1 = new BuyTicketThread("窗口1");
            buy1.start();
            BuyTicketThread buy2 = new BuyTicketThread("窗口2");
            buy2.start();
            BuyTicketThread buy3 = new BuyTicketThread("窗口3");
            buy3.start();
        }
    }
2.实现Runnable接口
  public class BuyTicketThread implements Runnable{
    int ticketNum = 10;
    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            if (ticketNum > 0){
                System.out.println("我在"+Thread.currentThread().getName()+"买到了第"+ ticketNum-- +"张北京到邯郸的车票");
            }
        }
    }
  }
  public class Test {
    public static void main(String[] args) {
        //定义一个线程对象
        BuyTicketThread buy = new BuyTicketThread();
        //窗口1买票
        Thread thread1 = new Thread(buy,"窗口1");
        thread1.start();
        //窗口2买票
        Thread thread2 = new Thread(buy,"窗口2");
        thread2.start();
        //窗口3买票
        Thread thread3 = new Thread(buy,"窗口3");
        thread3.start();
    }
  }
3.实现Callable接口
  对比方式1和方式2,都需要有一个run方法,但是这个run方法有不足之处:没有返回值,不能抛出异常。
  基于上面两个不足,在JDK1.5之后出现了第三种创建多线程的方式:实现Callable接口:有返回值,可以抛出异常,但是创建比较麻烦。
  public class TestCallable implements Callable<Integer> {

      /**
       * 实现Callable接口可以不带泛型,如果不带则返回值是object类型
       * @return
       * @throws Exception
       */
      @Override
      public Integer call() throws Exception {
          return new Random().nextInt(10);//返回10以内的随机数
      }
  }

  public class Test {
      public static void main(String[] args) throws ExecutionException, InterruptedException {
          //定义一个线程对象
          TestCallable tc = new TestCallable();
          FutureTask ft = new FutureTask(tc);
          Thread thread = new Thread(ft);
          thread.start();
          //获取线程的返回值
          Object obj = ft.get();
          System.out.println(obj);
      }
  }

方式1继承Thread类和方式2实现Runnable接口,实际开发中哪个方式更好?

  方式1在Java单继承中具有局限性,继承了Thread类,就不能继承其他类了。
  方式2的共享资源能力更强一些,变量不用加static来修饰也可以实现共享,方式1共享变量必须用static修饰。(为什么不用static也可以)

Thread类和Runnable接口有什么关系?

  Runnable接口--实现-->Thread类,即Thread类实现了Runnable接口。(方式2的线程类实现了Runnable接口,方式1的线程类继承了Thread类。)

线程的生命周期

  新生状态、就绪状态、执行状态、死亡状态、阻塞状态。
  Thread thread = new Thread();新生状态-----start启动----》就绪状态(等待CPU调度)----run()获取cpu执行权--------》运行状态-------正常结束/出现异常/调用stop方法(不建议,该方法已废弃)----------》死亡状态
  Thread thread = new Thread();新生状态-----start启动----》就绪状态(等待CPU调度)----run()获取cpu执行权--------》运行状态-------阻塞事件----------》阻塞状态-------阻塞事件解除----------------》就绪状态

线程的常见方法

  start():启动当前线程,表面上调用start方法,实际上执行run方法。
  run():线程类继承Thread或者实现runnable接口的时候,都要重写run方法,run方法里面是线程要执行的内容。
  currentThread:Thread类中的一个静态方法,获取正在执行的线程。
  setName():设置线程名称
  getName():获取线程名称
  setPriority(int num):设置优先级别方法:同优先级别的线程采取先到先服务,使用时间片策略。如果优先级高,被CPU调度的概率就高。级别为:1-10,默认是5。
      /**
   * The minimum priority that a thread can have.
   */
  public final static int MIN_PRIORITY = 1;

 /**
   * The default priority that is assigned to a thread.
   */
  public final static int NORM_PRIORITY = 5;

  /**
   * The maximum priority that a thread can have.
   */
  public final static int MAX_PRIORITY = 10;

设置优先级别

  public class TestThread01 extends Thread{
      @Override
      public void run() {
          for (int i = 0; i < 10; i++) {
              System.out.println(i);
          }
      }
  }
  public class TestThread02 extends Thread{
      @Override
      public void run() {
          for (int i = 20; i < 30; i++) {
              System.out.println(i);
          }
      }
  }
  public class Test {
      public static void main(String[] args) {
          TestThread01 thread01 = new TestThread01();
          thread01.setPriority(10);//优先级别高
          thread01.start();
          TestThread02 thread02 = new TestThread02();
          thread02.setPriority(2);//优先级别低
          thread02.start();
      }
  }

join方法

  当一个线程调用了join方法,这个线程就会先被执行,它执行结束以后才可以去执行其余的线程。注意:必须先start,再join才有效。
  public class TestThreadJoin extends Thread{
      public TestThreadJoin(String name){
          super(name);
      }

      @Override
      public void run() {
          for (int i = 0; i < 10; i++) {
              System.out.println(this.getName()+"----------"+i);
          }
      }
  }
  public class Test {
      public static void main(String[] args) throws InterruptedException {
          for (int i = 0; i < 100; i++) {
              System.out.println("main-------------"+i);
              if (i==6){
                  //创建子线程
                  TestThreadJoin ttj = new TestThreadJoin("join子线程");
                  ttj.start();
                  ttj.join();//等子线程执行完再执行主线程。子线程打印0-9
              }
          }
      }
  }

sleep方法

sleep人为制造阻塞事件
public class Test {
  public static void main(String[] args) throws InterruptedException {
      DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
      Date date = new Date();
      String format = dateFormat.format(date);
      System.out.println(format);
      Thread.sleep(3000);
  }
}

设置伴随线程

  将子线程设置为主线程的伴随线程,主线程停止的时候,子线程也不要继续执行了。不会立马结束,会垂死挣扎一会。
  public class TestThread extends Thread{
      @Override
      public void run() {
          for (int i = 0; i < 100; i++) {
              System.out.println("子线程--"+i);
          }
      }
  }
  class Test{
      public static void main(String[] args) {
          //创建并启动子线程
          TestThread thread = new TestThread();
          thread.setDaemon(true);//设置伴随线程,先设置,再启动
          thread.start();
          //主线程输出1到10
          for (int i = 0; i < 10; i++) {
              System.out.println("main---"+i);
          }
      }
  }

stop方法

//终止当前线程。
public class TestStop{
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            if (i==6){
                Thread.currentThread().stop();//过期方法,不建议使用
            }
            System.out.println(i);
        }
    }
}

标签:Java,Thread,笔记,start,static,线程,new,多线程,public
From: https://www.cnblogs.com/shaokai7878/p/16950796.html

相关文章

  • 一致性哈希通俗笔记
    一致性哈希ConsistentHashing,一种数据结构。内容参考自视频:一致性哈希-ConsistentHashing是什么?为什么系统设计面试中经常会提到?10分钟讲解一致性哈希|系统设计Syst......
  • 《图解TCP/IP》 阅读笔记 (第四章 4.1、4.2、4.3)
    第4章IP协议4.1IP即网络协议网络层主要由IP和ICMP协议组成。本章详谈IP协议。IP协议就相当于OSI七层模型中的第三层,网络层,实现的是点到点通信(要和传输层的端到端通信......
  • [转]【读书笔记】.Net并行编程高级教程--Parallel - stoneniqiu - 博客园
    一直觉得自己对并发了解不够深入,特别是看了《代码整洁之道》觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准。而且在《失控》这本书中也多次提到并发,......
  • java FileInputStream读取文件
    javaFileInputStream读取文件 publicstaticvoidreadFileData(StringfilePath)throwsIOException{FileclassFile=newFile(filePath);FileInputSt......
  • 快来领取,33个常用JavaScript功能已封装成方法,拿来即用
    在实际开发中,为了提高开发的效率,我们会把常用到的功能封装成方法,这样后期开发需要,拿来即用。 这里分享33个在实际开发中经常需要用到的功能(已封装成方法),分享给到大家......
  • SpringCloud Alibaba学习笔记
    该笔记整理至尚硅谷周阳老师的SpringCloud课程SpringCloudAlibaba篇SpringCloudAlibaba入门简介SpringCloudNetflix项目进入维护模式,SpringCloudNetflix将不再......
  • ElasticSearch学习笔记
    简介Elasticsearch是开源的全文搜索引擎,它可以快速地储存、搜索和分析海量数据。维基百科、StackOverflow、Github都采用它Elastic的底层是开源库Lucene。但是,你没......
  • Java学习笔记2
    6异常和断言6.1异常概述6.2异常的处理自定义异常finally语句6.3断言7输入输出及文件操作7.1流的概念标准的I/O流7.2文件随机文件流7.3字......
  • tomcat_动态java项目的目录结构和tomcat_与IDEA集成&创建web项目
    tomcat_动态java项目的目录结构:静态项目和动态项目:目录结构:java动态的目录结构:项目的根目录WEB-INF目录web.xml......
  • .Net gRPC学习笔记
    目录.NetgRPC学习笔记什么是RPC和本地调用有什么区别RPC模式RPC的三个过程为什么要使用RPCRPC和其他协议的区别RPC使用场景RPC的流程RPC核心概念术语什么是gRPC.NET官方的......