zoukankan      html  css  js  c++  java
  • 多线程

    1.多线程概述

    计算机的操作系统采用多任务和分时设计,多任务是指在一个操作系统中可以同时运行多个程序。每个程序对应一个进程,每个进程也可以产生多个线程。

    1.进程

    Process)是程序的一次动态执行过程,它对应了从代码加载,执行到执行完毕的一个完整过程,这个过程也是进程从产生,发展至消亡的过程。计算机系统中的多个进程轮流使用CPU资源,或者共享操作系统的 其他资源。

    进程是系统运行的基本单位。

    每一个进程都有自己独立的一块内存空间,一组系统资源。

    每一个进程的内部数据和状态都是完全独立的。

    在操作系统中可以有多个进程。

    2.线程

    线程是进程中执行运算的最小单位,可以完成一个独立的顺序控制流程。

    每个进程中,必须至少建立一个线程(这个线程称为主线程)来作为这个程序运行的入口点。如果一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”。

    3.多线程的好处

    1)充分利用CPU的资源。

    2)简化编程模型,一个既长又复杂的进程可以考虑分为多个线程

    3)带来良好的用户体验,CPU的效率提高,降低了用户等待的几率。

    4.主线程

    java程序启动时,一个线程立刻运行,该线程通常称为程序的主线程。Java中的public static void main()方法是主线程的入口,每个进程至少有一个主线程。它是程序开始就执行的。主线程的重要性:

    a) 它是产生其他子线程的线程

    b) 通常它必须最后完成执行,因为它执行各种关闭动作。

    2.实现多线程

      1.继承Thread类创建线程

    主要的语法:

    Thread thread=new Thread( );

    Thread类常用的方法

    构造方法

    说明

    Thread()

    分配新的Thread对象

    Thread(Runnable target)

    分配新的Thread对象,targetrun()方法被调用的对象

    Thread(Runnabel target,String name)

    分配新的Thread对象,targetrun()方法被调用的对象,name为新线程的名称

    Void run()

    执行任务操作的方法

    Void start()

    使该线程开始执行,java虚拟机调用该线程的run方法

    Void sleep(long millis)

    在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)

    String getName()

    返回线程的名称

    int getPriority()

    返回线程的优先级

    Void setPriority()

    更改线程的优先级(1-10级,提高执行的概率,不是绝对)

    Static Thread currentThread()

    返回当前正在执行的线程对象的引用

    Boolean isAlive()

    测试线程是否处于活动状态

    Void join()

    等待该线程终止(强行插队)

    Void interrupt()

    中断线程

    Void yield()

    暂停当前正在执行的线程对象,并执行其他线程(礼让,提高概率不是绝对)

      2.实现Runnable接口创建线程

    主要的语法:

    1. 实现Runnable接口的类及run()方法的重写
    2. MyRunnable  runnable=new MyRunnable(实现Runnable接口的类)

    Thread   thread=new Thread(runnable);

      3.start()方法和run()方法的区别

    调用start()方法表示该线程处于启动状态,等待操作系统分配资源执行run()方法中的代码,在多个线程处于启动状态时,线程是交替执行的,从而实现多线程

    直接调用run()方法和调用实例方法没有区别,程序是按顺序执行的,属于单线程执行模式。

    3.线程的状态

    java中,线程通常有五种状态,创建,就绪,运行、阻塞和死亡状态。

      第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。 
      第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。 
      第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。 
      第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspendwait等方法都可以导致线程阻塞。 

    第五是死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪。

    4.线程的调度

     1.线程的优先级

    多个线程处于运行状态时,它们需要排队等待CPU的资源,每个线程会自动获取一个线程的优先级(Priority)。一般情况下,优先级越高的线程获得CPU资源的概率较大,但不是绝对的,至少提高概率而已。

    线程的优先级用1~10表示,共有10个等级,1为最低,10为最高,系统默认为5.这些优先级对应一个Thread类的公用静态常量。

     2.线程的休眠

    语法: Thread.sleep(millis毫秒)

    Sleep方法会让当前线程休眠()停止执行millis毫秒,线程由运行状态进入不可运行状态,睡眠时间过后线程会再次进入可运行状态。

    调用Sleep()方法需要处理interruptedException异常。(try/catch

     3.线程的强制运行

    语法:Thread(线程对象).join();

    它有三个重载方法:

    1. Public final void join();
    2. Public final void join(long mills);
    3. Public final void join(long mills,int nanos);

    使当前线程暂停执行,强制执行插入的join对象的线程,等到线程执行完毕后,再执行当前线程。

    Jion()方法同样需要处理interruptedException异常。(try/catch

     4.线程的礼让

    Yield()方法可暂停当前线程执行,允许其他相同优先级的线程获得运行机会,该线程仍处于就绪状态,不会转为阻塞状态。

    线程的礼让只是提供一种可能,但是不能保证一定会实现礼让,因为礼让的线程也处于就绪状态,还有可能被线程调度程序再次选中。

    5.线程的同步

     1.多线程共享数据引发的问题

    由于多个线程并发执行操作同一共享资源时,将带来数据不安全的问题。

    比如创建多个线程模拟网络订票,会出现多个线程抢到同一张的票的问题,从而造成了同一共享资源数据的不安全。

     

     2.线程同步的实现

      1.同步的方法

    使用synchronized修饰的方法控制对类成员变量的访问。每个类实例对应一把锁,方法一旦执行就独占该锁,直到方法返回时,该锁才释放,此后被阻塞的线程方能获得该锁,重新进入执行状态。这种机制确保了同一时刻对应一个实例,从而有效避免了类成员变量的访问冲突。

    实现的语法:

    访问修饰符 synchronized 返回类型 方法名(参数列表){//方法体}

    或: synchronized 访问修饰符 返回类型 方法名(参数列表){//方法体}

    在语法中synchronized是同步关键字

    同步方法的缺陷:

     如果一个运行时间比较长的方法声明成Synchronized将会影响效率。如果将run()方法声明synchronized,由于在线程的整个生命周期内它一直在运行,因此就可能导致run()会执行很长的时间,那么其他的线程就需要一直等到run()方法结束了才能执行。

    解决方法:

    最好不要run()方法中声明

      2.同步代码块

    使用synchronized关键字修饰的代码块,称为同步代码块。语法如下:

    SynchronizedsyncObject{//需要同步的代码块}

    Synchronized块中的代码必须获得对象syncObject的锁才能执行,具体机制与同步方法一致,由于可以针对任意代码块,并且可以任意指定上锁的对象,因此灵活性更高。

       3.线程安全的类型

           1.线程的安全

    若在进程中有多个线程,而当这些线程同时运行,每次运行结果和单线程运行的结果时一样的,而且其他的变量值也和预期的是一样的,这样线程就是安全的。

           2.线程安全的类型概念

    一个类在被多个线程访问时,不管运行时环境执行这些线程由什么养的时序安排,它必须是以固定的,一致的顺序执行。这样的类型称为线程安全的类型。

           3.线程安全和非安全

    线程安全

    方法同步

    效率低

    多线程共享资源

    非线程安全

    方法不同步

    效率高

    单线程

           4.线程安全类型的实例

      1. shtable是线程安全的,不允许出现空值,方法同步;HashMap是非线程安全,允许出现空值,重速度清安全。两者都实现了Map接口,Hashtable继承了Dictionary类,HashMap继承AbstracyMap类。
      2. StringBufferStringBuilder都可以用来存储字符串变量,是可变的对象。区别在于StringBuffer是线程安全的,而StringBuilder是非线程安全的。
  • 相关阅读:
    05-3. 六度空间 (PAT)
    05-2. Saving James Bond
    05-1. List Components (PAT)
    04-3. Huffman Codes (PAT)
    04-2. File Transfer (PAT)
    04-1. Root of AVL Tree (PAT)
    03-3. Tree Traversals Again (PAT)
    03-2. List Leaves (PAT)
    03-1. 二分法求多项式单根(PAT)
    CDH Namenode自动切换(active-standby)
  • 原文地址:https://www.cnblogs.com/Eason-chen/p/7642551.html
Copyright © 2011-2022 走看看