多线程
一 并发 与 并行 
    并行:指两个或多个事件在 同一时刻 发生(同时发生)

    并发:值两个或多个时间在 同一个时间段内 发生, 即同一段时间内宏观上有多程序同时运行,微观上是分时的交替运行,多线程是实现并发机制的一种有效手段。
    
    注:单核处理器的计算机肯定是不能并行的处理多个任务的,只能是多个任务在单个CPU上并发运行。同
    理,线程也是一样的,从宏观角度上理解线程是并行运行的,但是从微观角度上分析却是串行运行的,即一个
    线程一个线程的去运行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为
    线程调度。

二 进程 与 线程
    1.进程 指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;
            进程也是程序的依次执行过程,是系统运行程序的基本单位;
            系统运行一个程序即是一个进程从创建、运行到消亡的过程。
    2.线程 进程内部的一个独立执行单元,一个进程可以同时并发的运行多个线程

    3.进程 与 线程 的区别
        1)进程 有独立的内存空间,进程中的数据存放空间(堆空间和栈空间)是独立的,至少有一个线程。
        2)线程 堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小的多。
    注意:
        1)因为一个进程中的多个线程是并发运行的,那么从微观角度看也是有先后顺序的,哪个线程执行完全取决于
            CPU 的调度,程序员是干涉不了的。而这也就造成的多线程的随机性。
        2)Java 程序的进程里面至少包含两个线程,主进程也就是 main()方法线程,用于启动子线程,另外一个是垃圾回收机制线程,负责垃圾回收。每
            当使用 java 命令执行一个类时,实际上都会启动一个 JVM,每一个 JVM 实际上就是在操作系统中启动了一个
            进程,java 本身具备了垃圾的收集机制,所以在 Java 运行时至少会启动两个线程---main线程 和 gc线程。
        3) 由于创建一个线程的开销比创建一个进程的开销小的多,那么我们在开发多任务运行的时候,通常考虑创建
            多线程,而不是创建多进程。
    4.线程调度
            计算机通常只有一个CPU时,在任意时刻只能执行一条计算机指令,每一个线程只有获得CPU的使用权才能执行指
        令。所谓多线程并发运行,从宏观上看,其实是各个线程轮流获得CPU的使用权,分别执行各自的任务。那么,在可运行
        池中,会有多个线程处于就绪状态等到CPU,JVM就负责了线程的调度。JVM采用的是 抢占式调度 ,没有采用分时调度,
        因此可以能造成多线程执行结果的的随机性。
    5.线程类
        java.lang.Thread类代表线程,所有的线程UI想都必须是Tread类或者其子类的实例
        1)创建并启动多线程步骤
            (1) 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把
                run()方法称为线程执行体。
            (2) 创建Thread子类的实例,即创建了线程对象
            (3) 调用线程对象的start()方法来启动该线程
    6.常用方法
        1)构造方法
            public Thread()
                分配一个新的线程对象
            public Thread(String name)
                 分配一个指定名字的新的线程对象
            public Thread(Runnable target)
                分配一个带有指定目标新的线程对象
            public Thread(Runnable target, String name)
                分配一个带有指定目标新的线程对象并指定名字
        2)方法
            public final String getName()
                获取当前线程名称
            public  final String setName()
                设置线程名字
            public void start()    
                执行线程,Java虚拟机调用次线程的 run()方法
            public void run()
                此线程要执行的任务在此处定义代码
            public static Thread currentThread()
                返回当前正在执行的线程对象的引用

    7.创建线程的方式
        1)继承Thread类
        2)实现Runnable接口
            (1)创建步骤
                    (a)定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
                    (b)创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正
                        的线程对象。
                    (c) 调用线程对象的start()方法来启动线程。
        3)缺点
            不能返回操作结果
    8.线程安全
        1)概念
            如果有多个线程在同时运行,而这些线程可能会同时运行这段代码,程序每次运行结果和单线程运行的结果是一样的,二且其他的变量的值也和语气的是一样的
        2)产生原因
            线程安全问题都是由 全局变量 及 静态变量 引起的。若每个线程中对全局变量、静态变量只有读操作,而无写
            操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,
            否则的话就可能影响线程安全。
    9.线程同步
        1)多线程面对的问题: 多线程同时处理资源比单线程高很多,但是多个线程操作同一资源会出现不同步的问题(资源操作的完整性)

        2)同步操作就是在一个代码块中,多个线程操作在同一个时间段内只能有一个线程执行,其它线程需要等待此线程完成后才能够执行。

        3)Java提供了同步机制(synchronized)来解决这个问题,synchronized 关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。

        4)同步操作三种方法
            (1)同步代码块
                synchronized(同步锁){
                    需要同步操作的代码
                }
            (2)同步锁 (同步代码块,Java中有4种代码块: 普通代码块、构造块、静态块、同步块)
                    (a)锁对象,可以是任意类型
                    (b)多个线程对象要使用同一把锁
                    注:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他线程只能在外等候(BLOCKED)
            (2)同步方法
                    public synchronized void method(){
                        可能会产生线程安全问题的代码
                    }
            (3)锁机制 Lock
                    public void lock()
                        加同步锁
                    public void unlock()
                        释放同步锁
                注:java.util.concurrent.locks.Lock 机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,
                同步代码块/同步方法具有的功能Lock都有,除此之外更强大,更体现面向对象。
        注:1)同步的代码块性能很低,但是数据的安全性会高,称为线程安全性高
            2)过多的同步操作可以能会带来 死锁 问题,进而导致程序进入停滞状态

    10.线程状态
            (1)五种状态
                    创建、就绪、运行、堵塞、总之
            (2)当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态
                    线程状态                      导致状态发生条件

                NEW(新建)             线程刚被创建,但是并未启动。还没调用start方法。

                Runnable(可运行)        线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。

                Blocked(锁阻塞)        当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。

                Waiting(无限等待)    一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。Timed

                Waiting(计时等待)    同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、Object.wait。
                                    public static void sleep(long millis) throws InterruptedException

                Teminated(被终止)    因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

    11.多线程两种实现方式的区别
        
        不同
        1)    使用  Ruunable接口 可以避免单继承的局限性
        2) Ruunable接口    比 Thread类 可以更好的实现数据共享的概念
        相同 
        1) 多线程两种实现都需要一个线程的朱磊,这个主类实现 Ruunable接口 或者 继承 Thread类,不管使用哪种方式子类都必须覆写 run() 方法 ,此方法为线程的主方法。

    12.利用 Callable接口 实现多线程
        1)从 JDK1.5 开始增加此接口,可以返回一个值。
            @FunctionalInterface
            public interface Callable<V> {
                public V call() throws Exception;
            }
        2)Thread类 如何接收 call()的返回值
            (1)使用 FutureTask类,它实现了RunnableFuture接口,而 RunnableFuture接口 又实现了 Runnable接口 和 Future 接口。
                这样FutureTask的对象作为Runnable接口的子类可以被Thread类接收;作为Future的子类,可以使用Future接口的 get()方法来获取返回值。
            (2)FutureTask类 常用方法
                    public FutureTask(Callable<V> callable)
                        本构造方法接收Callable接口实例
                    public FutureTask(Runnable runnable, V result)
                        本构造方法接收Runnable接口实例,并指定返回结果类型
                    public V get() throws Interrupted Exception, ExceutionException
                        取得线程操作结果,此方法为Future接口定义
        3)Callable接口 与 Runnable接口 优缺点
            Callable接口 比 Runnable接口 多了一个获取返回值的功能,但Runnable接口使用最早,最广泛,所以实现多线程时优先考虑Runnable接口
    13.线程的优先级
        1)线程的优先级越高,越有 可能 先执行
                            常量
            最高优先级    MAX_PRIORITY        数值为 10
            中等优先级    NORM_PRIORITY        数值为 5
            最低优先级    MIN_PRIORITY        数值为 1
        2)方法
            public final void setPriority(int newPriority)
                设置线程优先级
            public final int getPriority()
                获得线程优先级
        注:main()方法的优先级为 5
    14.多线程中数据交互情况
        概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。
        1)两点问题
            (1)数据错位
                原因:非同步的操作
                解决:要使用同步处理(不同的操作想要同步控制,需要放在一个类里面)
            (2)数据重复
                原因:没有使用唤醒机制
                解决: Object类的操作线程的方法
                    public final void wait() throws InterruptedException
                        线程的等待
                    public final void notify()
                        唤醒第一个等待线程
                    public final void notifyAll()
                        唤醒全部等待线程(哪个优先级高,哪个线程就有可能先执行)
                    注:在方法中增加一个标志位,来判断是否执行某个操作或者 Waiting
    15.注意
        1)suspend()方法
            resume()方法
            stop()方法
            这上个方法在操作时候容易产生 死锁 的问题,所以不建议使用。
        2)在多线程开发中,可以通过设置标志位的方式停滞一个线程的运行(覆写 stop()方法)

        3)调用wait和notify方法需要注意的细节
            (1) wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notify唤醒使用同一个锁对
                    象调用的wait方法后的线程。
            (2) wait方法与notify方法是属于Object类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继
                    承了Object类的。
            (3) wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方
                    法。