1-线程的创建以及运行

什么是线程

  • 进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。线程则是进行的一个执行路径一个进程中至少含有一个线程,进程中的多个线程共享进程的资源。
  • 操作系统在分配资源的时候是把资源分配给进程的,但是CPU资源比较特殊,它是分配给线程的,因此真正要占用CPU资源的是线程,线程是CPU分配的基本单位。
  • 在java中,启动main函数其实就是启动了一个JVM进程,而main函数所在的线程就是这个进程中的一个线程,也称主线程。
  • 进程和线程的关系如图所示:
    • image
    • 如图:每一个进程会有若干个线程,多个线程之间共享进程中的堆和方法区资源。但是每个线程都有自己的程序计数器金和栈区。
    • 程序计数器是一块内存区域,用来记录当前要执行指令的地址,那么为何要将程序计数器设为私有的呢?原因是线程才是CPU执行的基本单位,而CPU一般使用的是时间片轮转的方式让线程轮询占用。所以当前线程CPU时间片用完后,就要让出CPU,等下次轮到自己的时候再执行。这就需要程序计数器记录当前CPU执行到哪里了,下一步该执行的指令地址是什么,等下次该线程再次分配到CPU时间片之后就可以从私有的程序计数器中读取并继续执行。
  • 每个线程都有自己的栈资源,用于存储该线程的局部变量,这些局部变量是线程私有的,其他线程所不能访问的。
  • 堆是一个进程中最大的一块内存,堆倍进程中的所有线程都是共享的,是创建进程的时候分配的,堆里面主要存放的是new操作创建的对象实例。
  • 方法区用来存放的是JVM加载的类,常量以及静态变量等信息,也是线程共享的。

线程创建与运行

  • java中有三种创建线程的方式

      1. 实现Runnable接口的run方法 没有返回值
      2. 继承Threag类并重写run方法 没有返回值
      3. 使用FutureTask方式 有返回值
  • 继承Thread方法

    • package com.heiye.learn1;
      
      public class ThreadTest {
          //继承Thread类并重写run方法
          public static class MyThread extends Thread {
              @Override
              public void run() {
                  System.out.println("I am a child thread");
              }
          }
      
          public static void main(String[] args) {
              //创建一个线程
              MyThread myThread = new MyThread();
              //启动线程
              myThread.start();
          }
      }
      
    • 上图中的MyThread类继承了Thread类,并重写了run方法。在main函数里创建了一个MyThread实例,然后调用该实例的start()方法启动了线程。当创建完thread对象后该线程并没有立刻执行,直到调用了start()方法后就算真正的启动了线程,但是并没有立刻执行而是处于就续状态,这个就绪状态指的是该线程已经获取到了除CPU以外的资源,等待获取到CPU资源后才会真正的处于运行状态,一旦run方法执行完毕后,该线程就会处于终止状态。

  • 实现Runnable接口的run方法

    • package com.heiye.learn1;
      
      public class RunnableTask implements Runnable{
          @Override
          public void run() {
              System.out.println("I am child thread");
          }
      
          public static void main(String[] args) {
              RunnableTask task=new RunnableTask();
              new Thread((task)).start();
          }
      }
      
  • 使用FutureTask方法

    • package com.heiye.learn1;
      
      import java.util.concurrent.Callable;
      import java.util.concurrent.ExecutionException;
      import java.util.concurrent.FutureTask;
      
      public class CallerTask implements Callable<String> {
          @Override
          public String call() throws Exception {
              return "hello";
          }
      
          public static void main(String[] args) {
              //创建异步任务
              FutureTask<String> futureTask = new FutureTask<>(new CallerTask());
              //启动线程
              new Thread(futureTask).start();
              try {
                  //等待执行结束后返回结果
                  String result = futureTask.get();
                  System.out.println(result);
              } catch (ExecutionException | InterruptedException e) {
                  e.printStackTrace();
              }
          }
      }
      
    • CallerTask类实现了Callable接口的call()方法,在main函数中创建了一个FutureTask对象,构造函数为CallerTask实例,然后使用FutureTask对象作为任务创建一个线程并启动它,最后通过futureTask的get()方法获取到线程执行完后返回的结果。

posted @ 2021-09-22 14:58  LilyFlower  阅读(140)  评论(0编辑  收藏  举报