Java(Thread多线程)

一、多线程

1、串行 & 并行 & 并发 的区别

串行:顺序执行代码
并行:在一个时间刻度上【不可分割】,执行的多条路径,多核处理器(同时执行)
并发:在同一段时间内【可分割】,执行的多条路径,同一时间抢票(交替执行)

2、线程 & 进程 的区别

1)进程:
    进程是指内存中运行的一个应用程序,一个进程由一个或多个线程组成
    进程是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序就是一个进程从创建运行到消亡的过程
    进程是操作系统分配资源的最小单位


2)线程:
    线程是进程中的一条执行路径,一个进程中可以有多个线程;
    线程是程序执行的最小单位

3)进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信号等),某进程内的线程在其他进程不可见;
4)调度和切换:线程上下文切换比进程上下文切换要快得多

3、多线程的好处

效率高,提高CPU使用率
多个线程之间互不影响

4、线程调度

1)分时调度:
    所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间
2)抢占式调度:
    优先让优先级高的线程使用CPU,如果优先级相同,则随机选择(概率问题)

5、Java的多线程是采用什么模式来执行的?

是采用抢占式调用模式来抢占资源,无法人为控制
多线程的效果看上去是同时间执行多个线程,其实不是
本质上,多条路径(多线程),先后顺序执行(抢占式调用模式)肉眼无法判断

6、在Java中至少开启几条线程?

至少两条:1、main方法 2、垃圾回收机制(GC)

7、开启线程(本质上两种)

第一种:继承Thread类

实现步骤:
    1、先自定义一个类,继承Thread类
    2、在子类中重写run方法,并编写线程任务
    3、创建子类线程对象
    4、调用Thread类中start()方法开启线程
注意事项:
    1、开启线程是调用start()方法,不是直接调用run()方法
    2、线程不能开启多次,会报错IllegalThreadStateException

第二种:实现Runnable接口

实现步骤:
    1、创建一个Runnable接口的实现类
    2、在实现类中 重写run方法,并在run方法中编写任务
    3、创建一个Runnable接口的实现对象
    3、创建Tread类的对象,构造方法里面传入Runnable接口的实现类对象
    4、调用Thread类中start方法开启线程

实现Runnable接口创建多线程的好处:
    1、避免了单继承的局限性
    2、增强了程序的扩展性,降低了程序的耦合性(解耦)

第三种:实现Callable接口(带线程任务的返回值)

实现步骤:
    1、自定义一个类,实现Callable接口,需要确定泛型;class CalcThread implements Callable<Integer>{}
    2、在自定义类中重写call方法 ,返回需要返回类型的结果;
    3、创建自定义类对象;CalcThread ct = new CalcThread(1, 100);
    4、创建FutureTask接口对象;FutureTask<Integer> task = new FutureTask<>(ct);    
    5、创建Thread类对象,构造方法传入FutureTack对象;Thread thread = new Thread(task);
    6、启动线程;thread.start();
    7、需要得到返回结果的话,需要借助一个get()方法;Integer integer = task.get();//ExecutionException

第四种:匿名内部类实现线程创建

1、概念
    匿名:没有名字
    内部类:写在其他类内的类

2、匿名内部类作用:简化代码
    把子类继承父类,重写父类的方法,创建子类对象,一起一步完成
    把实现类实现类接口,重写接口中的方法,创建实现类对象,一起一步完成

3、匿名内部类的最终产物:子类/实现类对象,而这个类没有名字

4、格式:
    new 父类/接口(){
      重写父类/接口中的方法
    };

5、代码实现
      //匿名内部类开启线程,有重写run方法//继承Tread类的方法
        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("匿名内部类(继承Thread类)"+i);
                }
            }
        }.start();

      //匿名内部类对象开启线程,实现Runnable的方式,重写run
          new Thread((new Runnable() {
              @Override
              public void run() {
                  for (int i = 0; i < 100; i++) {
                      System.out.println("匿名内部类(实现Runnable接口)"+i);
                  }
              }
          })).start();

    //继承Tread的类和实现Runnable接口的方式一起写,以Thread优先
        new Thread(new Runnable() {
            @Override
            public void run() {
                ///Runnable
                for (int i = 0; i < 100; i++) {
                    System.out.println("(实现Runnable接口)"+i);
                }
            }
        }){
            //Thread类
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println("(继承Thread)"+i);
                }
            }
        }.start();

8、run() & start() 的区别

run() :调用run方法就相当于调用自己类的方法,没有多线程的效果;只有一条执行路径
start():会有多条执行路径

9、Thread类的方法

构造方法
    Thread() 分配一个新的 Thread对象。 
    Thread(String name) 分配一个新的 Thread对象。可定义线程名称
    Thread(Runnable target, String name) 分配一个新的 Thread对象。可定义线程名称

成员方法
     getName() 获取线程名称
     setName(String name) 设置线程名称。 
     getPriority() 返回此线程的优先级。
     setPriority(int newPriority) 更改此线程的优先级。  
     sleep(long millis) 线程休眠,传入毫秒值
     yield() 线程礼让
     join() 线程加入,等待这个线程死亡
     start() 开启线程
     run() 此线程要执行的任务在此处定义代码
     currentThread() 返回当前正在执行的线程对象的引用

字段
      static int MAX_PRIORITY 线程可以拥有的最大优先级。  10
      static int MIN_PRIORITY 线程可以拥有的最小优先级。  1
      static int NORM_PRIORITY 分配给线程的默认优先级。5

10、线程的优先级

特点:
    1、是随机分配的,采用抢占式调度模式来抢占cpu资源
    2、根据优先级去分配执行资格,
        优先级高的线程得到的执行cpu执行权的时间片段比优先级低的线程更多
        如果多个线程优先级是相同对的,系统会随机分配cpu抢占时间

    3、优先级高的并不一定先完成任务

11、多线程的原理

posted @ 2021-03-08 20:44  一名初学者  阅读(220)  评论(0)    收藏  举报