多线程 Thread Runnable

多线程
    1.并行和并发
        并行:在同一时刻,有多个任务同时执行
        
        并发:在同一个时间段内,有多个任务"同时"执行。在同一时刻只能操作同一个任务
        
                   执行单元 --- 执行路径  -- 执行任务 -- 执行事件 说的是同一个东西

        单核 CPU 在某一时刻上 只执行 一个路径(任务) 一个线程

        我们看到的同时执行 其实就是并发

        JAVA中 线程的调度模式  抢占式 

    2.进程和线程:
        进程  
           正在运行的程序 
           当一个程序开始运行,进入内存之后 就产生了进程 
                  创建---运行---消亡

        线程
           进程内部的执行单元,执行路径
           一个进程中至少有一个执行路径 也就是说 一个进程中至少有一个线程
           也可以有多条执行路径,也就是说可以有多个线程并发的执行,那么这样的程序就成为多线程程序

           迅雷 软件 打开 进入内存----------形成了一个进程 

           我们可以多任务下载
              多个任务下载 其实就是开启了多个 执行路径

              那么 就是说 迅雷程序执行的时候 并发的执行了 多个线程 

              迅雷程序 就是  多线程程序
              
              
        进程和线程的区别:
            进程:有独立的内存空间(栈和堆),就是每一个应用程序都有独立的内存空间(栈和堆)
            
            线程:每一个线程都是一个独立的栈空间,如果有多个线程那么这些线程共享同一个堆(必须是同一个进程中)

        
        在同一个执行路径中(栈),执行代码都是从上至下执行。
        
        
    3.如何开启新的线程 
        第一种方式:
           1:创建自定义类 继承Thread
           2:重写run方法  写新的线程执行的代码
           3:创建自定义类对象 调用strat方法  

           
           
        第二种方式:
            1: 创建自定义类 实现Runnable接口 (线程目标接口  线程任务接口)
            2: 实现run方法 (定义线程要执行的任务)
            3: 创建自定义类对象,并将此对象作为 Thread线程对象的构造参数 传递
            4: 使用线程对象调用start方法 开启新的线程

             Thread(Runnable target) 创建一个带有执行目标的线程对象
             Thread(Runnable target,String name) 创建一个带有执行目标的 给定线程名称的线程对象
             
             
        只有Thread类能够开启线程。


    4.设置(获取)线程的名称
         Thread(String name);//通过Thread类中的构造方法,对线程名称进行设置
        
         setName(String name);//通过set方法
        
         String name = getName();//获取线程名称
        
        
    5.Thread类中常用的方法: 
    
        a > Thread 的构造方法
             Thread() 空参  采用默认的起名字规则 Thread-0 开始

             Thread(String name) 给线程起名字的构造

             Thread(Runnable target) 创建一个带有执行目标的线程对象
             Thread(Runnable target,String name) 创建一个带有执行目标的 给定线程名称的线程对象

        b>  常用方法
               String getName() 获取线程的名称
               void setName(String name) 设置线程名称
               void start() 开启新的线程
               void run() 这个方法中定义线程要执行的任务,在run方法中代码都是线程需要执行的代码

        c > 静态方法
             获取正在执行的线程对象   谁执行当前代码 那个正在执行的线程对象就是谁

             static Thread currentThread()

             static void sleep(long time) 当前执行线程休息一会
             使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)    
                
                
    线程的实现总结:
        第一种方式:继承Thread类
            第一步:定义一个类去继承Thread类
            
            第二步:重新run方法
            
            第三步:将我们需要完成代码写入到run方法中
            
            第四步:创建Thread子类对象
            
            第五步:开启线程,调用start方法
        
        
        
        第二种方式:实现Runnable接口
            第一步:定义一个实现类,去实现Runnable接口
            
            第二步:重新run方法
            
            第三步:将我们需要完成代码写入到run方法中
            
            第四步:创建Runnable实现类对象
                Runable接口中并没有开启线程的方法,如果我们想开启线程,必须要借助于
                Thread类。
            
            第五步:将Runnable实现类对象,作为参数传递给Thread构造方法。
            
            第六步:使用Thread类的start方法开启线程
        
        
    6.两种实现线程的区别
        类继承的特点:
            单继承。如果一个类继承了Thread就不能再继承其他类。
            
        接口的特点:
            一个类可以实现多个接口,同时还可以继承一个类。
            
            
        接口的出现就是为了打破类的单一继承性。
        
        Thread 与  Runnable 区别 

           如果一个类 继承Thread,就不能再继承其他的类。 不适合资源共享 
           
           如果实现了 Runnable接口,并且可以再去继承其他的类。 可以实现资源共享

        Runnable优势
         1:适合多个相同的程序代码的线程 去共享同一资源
         2:可以避免单继承的局限性
         3: 增加了程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程是独立的。
         4: 线程池只能放实现Runnable或Callable的线程,不能直接放继承Thread类
            
            
    7.使用匿名内部类的方式 开启线程(了解)
        什么是匿名内部类

        本质
            实现一个接口或者继承一个类 的 子类对象

        格式
            new 接口名/类名(){
                 重写方法
            }

        实现线程开启的方式 二
         1:创建自定义类  Runnable的实现类
         2:重写run方法
         3:创建实现类对象
         4:创建Thread对象 构造中传递 实现类对象
         5:开启线程


        划重点
            new Thread(线程执行目标).start();
            new Thread(Runnable的实现类对象).start();    
        

    8.java中同步机制:
        当一个线程中的代码加上同步之后,这个线程执行不完,其他线程是无法进来执行的。
        起到一个保护的作用,就是提高代码的安全性。
        
        a>  同步代码块(静态代码块,局部代码块,构造代码块)
        
            sychronized 关键字  可以用在某个方法中的某块区域
            表示只对这个区域的资源实现互斥访问(同时只有一个线程进行操作,其他线程没有权限操作)。

            格式
             synchronized(锁对象){//锁对象,可以是任意对象
                 需要进行同步操作的代码
             }
            锁对象又称同步锁 只是一种概念 可以想象为在对象上标记了一个锁
              1:锁对象可以是任意类型
              2:多个线程 使用同一把锁

            提示 在任何时候 最多允许一个线程拥有同步锁,其他线程只能在外面等待
            
            
            如果多个线程使用同步代码块,要求这些线程的同步锁对象必须是同一个对象:
                可以使用本类的字节码文件对象。
                在成员的位置定义一个对象,使用static修饰
            
        b> 同步方法:锁是默认的
            同步方法  使用synchronized关键字修饰方法 就是同步方法
            保证线程A在执行该方法的时候 其他线程只能等待

            格式
                public synchronized void method(){
                  可能出现线程安全问题的代码
                }

            同步锁是谁呢?
                如果是 非静态方法  同步锁 就是this
                如果是 静态方法  同步锁 当前方法所在类的字节码文件对象  (类名.class)
        
        c> Lock锁
            使用Lock锁 解决线程安全问题
            JDK1.5 以后出现的
            Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作

               更灵活
               获取锁对象 : Lock lock = new ReentrantLock();
               定义了两个方法
                  lock()    加锁
                  unlock()  释放锁

              接口 java.util.concurrent.locks.Lock
              实现类  ReentrantLock
        
    
        
    9.线程的状态(JVM状态)
        新建  -- 运行 -- 阻塞 -- 无限等待 -- 计时等待 -- 死亡
        
        a> 计时等待
            void sleep(long time);
                让当前线程睡眠多长时间,

                    在同步中睡眠的时候不释放锁资源。
                    
                    在非同步中和锁无关。
                
            void wait(long timeout);//如果时间到了,会自动醒来
                让当前线程等待多长时间,在等待的时候是会释放锁资源
 
        
        b> 锁阻塞
            
        c> 无限等待
            void wait();//这种无限等待需要另外的线程来唤醒,如果不换醒那么永远处于等待状态。
        
            Wating状态在API中介绍为:
             一个正在无限期等待另一个线程执行一个特别的(唤醒)动作的线程处于这一状态。

             调用 wait()方法 可以让 正在执行的线程 进入 无限等待状态

             调用 notify()方法 可以让 正在等待的线程 脱离无限等待状态
                随机唤醒一个正在等待的线程

             调用notifyAll() 可以让 所有正在等待的线程 脱离无限等待状态
                唤醒所有正在等待的线程
                
                
             这仨方法 来自Object


             wait() 方法这里  有句话
                 当前线程必须拥有此对象监视器 (同步锁)
                 简而言之 wait()方法想要调用 有两个条件
                 1:必须在同步中
                 2:必须使用同步锁调用

             notify()方法这里
                唤醒在此对象监视器上等待的单个线程。
                 简而言之
                  1:必须在同步中
                  2: 必须使用同步锁调用

                 Thread.State getState()
                  返回该线程的状态。
                
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

猜你喜欢

转载自blog.csdn.net/snack_TC_dora/article/details/81138893