• 多线程


    1.线程与进程关系:

    • 进程(process)
      • 所有运行中的任务通常对应一个进程。
      • 当一个程序进入内存运行时,即变成一个进程。
      • 进程是处于运行过程中的程序。
      • 进程是系统进行资源分配和调度的一个独立单位。
      • 独立性:每个进程都有自己的地址空间,在没有经过进程本身允许的情况下,进程不可直接访问其他进程的地址空间。
      • 动态性:程序是一个静态的指令集合,而进程是一正在系统中活动的指令集和,进程具有自己的声明周期和不同的状态。
      • 并发性:多个进程可在单个处理器上并发运行,多个进程之间不会互相影响。
    • 线程(thread)  
      • 线程也被称为轻量级进程,线程是进程的执行单元。
      • 线程是进程的组成部分,一个进程可以有多个线程。
      • 一个线程必须有一个父进程。
      • 线程可以拥有自己的堆栈、计数器和自己局部变量,但不能拥有系统资源,它与父进程的其他线程共享该进程所拥有的全部系统资源。
      • 线程可以完成一定的任务,可以与其他线程共享父进程中的共享变量即部分环境,相互之间协同完成进程要完成的任务。
      • 线程是独立运行的。要确保线程不会妨碍同一进程里的其他线程。
      • 一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发运行。
    • 多线程存在于一个应用程序中,让一个应用程序中可以有多个执行部分同时执行,但操作系统无需讲多个线程看作多个独立的应用,对多线程实现调度和管理以及资源分配。线程的调度和管理有进程本身负责完成。
    • 一个程序运行后至少有一个进程,一个进程中可以包含多个线程,但至少要包含一个线程。

     2.线程的优势

    • 进程之间不能共享内存,但线程之间共享内存非常容易
    • 系统创建进程时需要为该进程重新分配系统资源,但创建线程则代价小的多,因此使用多线程来实现多任务并发比多进程的效率高。

    3.线程的创建

    • 继承Thread类创建线程类
    • ①定义Thread类的子类,并重写该类的run()方法,该run()方法的方法提就是线程
        需要完成的任务,因此run()方法成为线程的执行体。
      ②创建Thread子类的实例,及创建了线程对象。
      ③调用线程对象的start()方法来启动线程。
      public class FirstThread extends Thread
      {
          private int i ;
          // 重写run方法,run方法的方法体就是线程执行体
          public void run()
          {
              for ( ; i < 100 ; i++ )
              {
                  // 当线程类继承Thread类时,直接使用this即可获取当前线程
                  // Thread对象的getName()返回当前该线程的名字
                  // 因此可以直接调用getName()方法返回当前线程的名
                  System.out.println(getName() +  " " + i);
              }
          }
          public static void main(String[] args)
          {
              for (int i = 0; i < 100;  i++)
              {
                  // 调用Thread的currentThread方法获取当前线程
                  System.out.println(Thread.currentThread().getName()
                      +  " " + i);
                  if (i == 20)
                  {
                      // 创建、并启动第一条线程
                      new FirstThread().start();
                      // 创建、并启动第二条线程
                      new FirstThread().start();
                  }
              }
          }
      }
    • 实现Runnable接口创建线程类
    • ①定义Runnable接口的实现类
      ②创建Runnable实现类的实例
      ③调用线程对象的start()方法启动多线程
      public class SecondThread implements Runnable
      {
          private int i ;
          // run方法同样是线程执行体
          public void run()
          {
              for ( ; i < 100 ; i++ )
              {
                  // 当线程类实现Runnable接口时,
                  // 如果想获取当前线程,只能用Thread.currentThread()方法。
                  System.out.println(Thread.currentThread().getName()
                      + "  " + i);
              }
          }
      
          public static void main(String[] args)
          {
              for (int i = 0; i < 100;  i++)
              {
                  System.out.println(Thread.currentThread().getName()
                      + "  " + i);
                  if (i == 20)
                  {
                      SecondThread st = new SecondThread();     //// 通过new Thread(target , name)方法创建新线程
                      new Thread(st , "新线程1").start();
                      new Thread(st , "新线程2").start();
                  }
              }
          }
      }
    • 使用Callable和Future创建线程
    • ①创建Callable接口的实现类,并实现call()方法,将call()方法作为线程执行体,
      且该call()方法有返回值,在创建Callable实现类的实例。java8开始可使用Lambda表达式创建Callable对象。
      public class ThirdThread { public static void main(String[] args) { // 创建Callable对象 ThirdThread rt = new ThirdThread(); // 先使用Lambda表达式创建Callable<Integer>对象 // 使用FutureTask来包装Callable对象 FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() -> { int i = 0; for ( ; i < 100 ; i++ ) { System.out.println(Thread.currentThread().getName() + " 的循环变量i的值:" + i); } // call()方法可以有返回值 return i; }); for (int i = 0 ; i < 100 ; i++) { System.out.println(Thread.currentThread().getName() + " 的循环变量i的值:" + i); if (i == 20) { // 实质还是以Callable对象来创建、并启动线程 new Thread(task , "有返回值的线程").start(); } } try { // 获取线程返回值 System.out.println("子线程的返回值:" + task.get()); } catch (Exception ex) { ex.printStackTrace(); } } }

    4.创建线程三种方式的比较

    **实现Runnable接口与实现Callable接口方式基本相同,试试Calllable接口里定义的方法有返回值,可以声明抛出异常。

    • 创建线程一般推荐使用Runnable几口、Callable接口的方式。

     

  • 相关阅读:
    ATM+购物车
    subprocess,re,logging模块
    json,pickle,collections,openpyxl模块
    time,datatime,random,os,sys,hashlib模块
    1.内置函数剩余部分 map reduce filter 2.函数递归 3.模块
    生成器,面向过程编程,三元表达式,列表生成式,生成器表达式,匿名函数,内置函数
    Ajax数据对接出问题了?ThingJS解决方法在这里
    测试
    简单低成本的物联网开发平台-ThingJS
    用ThingJS之CityBuilder快搭3D场景,可视化开发必备
  • 原文地址:https://www.cnblogs.com/sjxbg/p/5552872.html
Copyright © 2020-2023  润新知