• Java基础视频笔记(八):多线程编程


    多线程编程:

    1、进程与线程

    线程:程序中单独顺序的控制流;
    线程本身依靠程序进行运行;
    线程是程序中的顺序控制流,只能使用分配给程序的资源和环境。
    进程:正在执行的程序;
    一个进程可以包含多个线程;
    一个进程至少要包含一个线程
    单线程:程序中只存在一个线程,实际上,主方法就是一个主线程;

    多线程:多线程是在一个程序中运行多个任务;

    多线程的目的:更好的使用CPU的资源;

    2、线程的实现

    两种方式:1、继承Thread类
     2、实现Runnable接口

    Thread类是在java.lang包中定义的,继承Thread类必须重写 run() 方法;


    创建线程:继承于Thread

     

    1. public class MyThread extends Thread {  
    2.     private String name;  
    3.   
    4.     //构造器 传参  
    5.     public MyThread(String name) {  
    6.         // 获取传入 MyThread 方法的字符串  
    7.         this.name = name;  
    8.     }  
    9.       
    10.     public void run() {  
    11.         // 打印  name 的同事,打印 J 的数值  
    12.         for (int j = 0; j < 20; j++) {  
    13.             System.out.println(name + ":" +j);            
    14.         }  
    15.         super.run();  
    16.     }  
    17. }  
    18.  


    线程的调用:

     

     

    1. public class ThreadDemo01 {  
    2.   
    3.     public static void main(String[] args) {  
    4.         // 调用 MyThread 类,启动线程  
    5.           
    6.         MyThread mt1 = new MyThread("A");  
    7.         MyThread mt2 = new MyThread("B");  
    8.         /*mt1.run(); 
    9.         mt2.run();*/  
    10.           
    11.         mt1.start();  
    12.         mt2.start();  
    13.     }  
    14.   
    15. }

     


    1、进程与线程


    进程:正在执行的程序;

    每个进程执行,都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元

    * 一个进程可以包含多个线程;


    * 一个进程至少要包含一个线程

    线程:程序中单独顺序的控制流;是进程中独立的控制单元;

    * 线程本身依靠程序进行运行;

    * 线程是程序中的顺序控制流,只能使用分配给程序的资源和环境。

    单线程:程序中只存在一个线程,实际上,主方法就是一个主线程;

    多线程:多线程是在一个程序中运行多个任务;

    多线程的目的:是更好的使用CPU的资源;


    JavaVM 启动的时候会有一个进程java.exe;

    该进程中至少一个线程负责Java程序的执行,

    而且这个线程运行的代码存在于main方法中,该线程称之为主线程;

    扩展:JVM启动不止一个线程,除了执行主函数代码,还有一条路径负责垃圾回收机制的线程;

            有多条执行路径,称为多线程。

    多线程存在的意义:

    多条代码同时执行,提高效率;

    2、线程的实现:自定义线程控制单元

    通过API的查找,Java已经提供了对这类事物的描述:
    java.lang 包 Thread:程序中的执行线程;

    两种方式:1、继承Thread类
     2、实现Runnable接口

    Thread类是在java.lang包中定义的,继承Thread类必须重写 run() 方法;

    /ThreadDemo/ThreadDemo01.java

    class Demo extends Thread{
    public void run(){// 重写run方法
    System.out.println("demo run");
    }
    }
    
    class ThreadDemo{
    public static void main(String[] args){
    // 建立好一个对象
    Demo d = new Demo(); // 就是创建好一个线程
    d.start(); // 使进程开始执行
      // start调用run()方法
    }
    }
    

      



    发现运行结果每一次都不同;

    因为多个线程都在获取CPU的执行权,CPU执行到谁,谁就运行;

    明确一点,在某一时刻,只能有一个程序在运行,多核除外;

    CPU 其实是在 快速的切换,以达到看上去是同时运行的效果;

    我们可以形象的把多线程的运行,形容为在互相抢夺CPU的执行权;

    这就是多线程的一个特性:随机性。 谁抢到谁执行,至于执行多长时间,是CPU说了算;

    为什么要覆盖 run() 方法?


    Thread类用于描述线程:

    该类定义了一个功能,用于存储线程要运行的代码,该存储功能就是run()方法;

    run() 就是存储线程要运行的代码。

    如果直接调用run()方法,只会被主线程单一执行,没有第二条执行路径,因为没调用start()启动线程控制单
    元。
    d.run(); 仅仅是对象调用方法,线程虽然创建了,但是没有开启
    d.start(); 开启线程并执行该线程的run方法


    3、线程的状态:

    sleep(time); // 时间一到,自然醒来
    wait(); // 不能自动恢复
    notify; // 主动唤醒wait()
    stop(); // 停止线程

    阻塞状态:临时状态,具备执行资格,但没有执行权;
    冻结状态:放弃了执行资格;
     * 唤醒时,先回到临时状态,获取执行资格;


    4、线程标识(线程名称)

    调用父类的私有对象 name 两种方法:

    1、getName();
    2、super(name);

    4、线程的常用方法


    currentThread();  获取当前线程对象
    getName(); 获取线程的名称
      设置线程名称:setName 或者 构造函数

    * 局部变量,在每一个线程区域中都有独立的一份地址;
       int x = 0; 所指的内存地址是不同的;

    * 全局变量  private static int ticket = 100; // 多个线程共用一个变量
    示例:卖票 TichetDemo.java
    如果定义静态,变量的生命周期较长,占用CPU 资源较多
    要实现Runnable接口解决:

    创建线程的第二种方式:实现 Runnable 接口

    步骤:  1、定义类实现Runnable接口
    2、覆盖Runnable接口的run方法
    3、通过Thread建立线程对象
    4、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
    5、调用Thread累的start方法开启线程并调用RUN你爸了本来、接口子类的run方法

          ¥¥经常考:实现接口和继承类的区别是什么?

    * 继承只能继承一次,当一个类已经继承了一个父类,此时就不能再继承Thread;

     此时就需要通过实现Runnable接口,调用线程执行代码;

    * 实现的好处,就是避免了单继承的局限性; 在定义线程时,建议使用实现方式、
     
    * 区别:存放代码位置不同

     继承Thread:线程代码存放Thread子类run方法中;

     实现Runnable:线程代码存在接口的子类的run方法中;

    接口的方法不能抛出异常,否则报错,只能try catch;
    try{Thread.sleep(10);}catch{Exception e};

    * 通过分析发现:打印出 0, -1, -2 等错票;

    * 多线程的运行,最担心出现安全问题;

    问题原因:

    * 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完;
     导致共享数据的错误;

    = = =
    Java对于多线程的安全问题提供了专业的解决方法:

    同步代码块;

    synchronized(对象){

    需要被同步的代码
    }

    ()里的对象就是“锁”;

    “同步代码块”相当于“上了锁”,使用的时候,其他线程就无法执行这块代码;

    同步的前提:
    1、必须要有两个或者两个以上的线程;
    2、必须是多个线程使用同一个锁
    3、必须保证同步中只能有一个线程在运行

    同步的好处:解决多线程的安全问题

    同步的弊端:多个线程都要判断是否有“锁”,消耗资源,变得稍慢;

    如何找问题:1、明确哪些代码是多线程与运行代码~
        2、明确共享数据;
        3、明确多线程运行代码中哪些语句是操作共享数据的;

    同步的两种方法:1、同步代码块;2、同步方法

  • 相关阅读:
    【codeforces 787B】Not Afraid
    【codeforces 787A】The Monster
    【codeforces 787C】Berzerk
    【t046】牛跳
    【BZOJ 1033】 [ZJOI2008]杀蚂蚁antbuster(判断线段是否和圆相交)
    Java Web整合开发(81)
    用户、权限管理
    链表
    T1230 元素查找 codevs
    T3139 栈练习3 codevs
  • 原文地址:https://www.cnblogs.com/jackchiang/p/4585222.html
Copyright © 2020-2023  润新知