JAVA中的多线程

几个基本的概念

  • 程序:代码的集合,是静态的

  • 进程:程序的一次执行(运行着的程序),是动态的

  • 线程:进程中可以并行执行的小任务(例如QQ,迅雷)
    操作系统中的

  • 进程:当一个程序进入内存运行时就变成了一个进程(是系统进行资源分配和调度的一个独立单位),具有独立性,动态性。并发性(程序是静态的指令集合,而进程是动态的)
    -线程:线程是进程的组成部分,是进程的执行单元,一个进程可有拥有多个线程,一个线程必须有父线程
    java中多线程的作用:

  • 发挥多核cpu的优势

  • 防止阻塞

  • 便于建模
    创建线程的方式

  • 继承Thread类,重写run()的方法
    用Thread创建多线程的常用步骤

  • 定义一个类(A),来继承Thread, 同时重写run方法

  • 创建线程对象 (A a=new A()????

  • 启动线程(a.start())

  • 实现Runnable接口

  • 定义一个类,实现Runnable接口;重写run方法;

  • 定义一个Thread(Runnable ),将Runnable作为参数传递给Thread
    后者相对来说好一些:实现接口的方式比继承跟家灵活 和方便,同时也能降低程序之间的耦合度。
    两个juc的方法

  • Callable接口(juc)

  • 线程池(juc)
    Volatile关键字的作用:

  • 多线程主要围绕可见性和原子性展开的,使用Volatile关键字修饰变量时保证了多线程之间的可见性,每次读取的Volatile变量都是最新的数据

  • Volatile禁止语义重排序,这在一定程度上降低了代码的执行效率
    什么是线程安全:

  • 不可变:像String,Long,Integer这些,都是final类,任何一个线程都改变不了他们的值,要想改变只能重新创建一个。

  • 绝对线程安全:CopyOnWriterArrayList

  • 相对线程安全:vector

  • 线程非安全:arraryList,LinkedList,HanshMap
    当多个线程对一个资源(对象,变量)进行操作时,可能会引发线程安全的问题
    资源竞争的问题:

  • 当多个线程访问一个资源时,可能会出现资源竞争的问题,我们可以通过同步锁来解决此问题,就是将访问的资源的代码放在同一个同步块或同步方法中,当需要执行此代码时,必须先得到锁才能执行,如果得不到锁不能执行,只能将线程放在锁池中等待其它线程释放锁。
    使用同步块或同步方法可以解决线程并发遇到的安全问题

  • 同步块:
    synchronized(monitor){

    }
    monitor可以时任何对象,要想运行同步块中的代码,必须先获得monitor,同一时刻只能使用同一个monitor的一个线程获得monitor对象,块中的代码执行完毕后,monitor会自动释放。
    同步方法中使用的monitor是this

  • 如果某个synchronized方法是static的,那么当线程访问该方法时它锁的并不是synchronized方法所在的对象,而是synchronized方法所在对象所对应的class对象,因为java中无论一个类有多少个对象,这些对象会对唯一一个class对象,因此当线程分别访问同一个类的两个对象的两个static.

  • synchronized方法,他们执行顺序也是顺序的,也就是说一个线程先去执行方法,执行完毕后另一个线程才开始执行。

  • 关于成员变量与局部变量:如果一个变量是成员变量,那么多个线程对同一个对象的成员变量进行操作时,他们对该成员变量是彼此影响的(也就是说一个线程对成员变量的改变会影响到另一个线程)
    守护线程

  • 该线程的优先级比较低,如果进程中只有守护线程还在运行,那么操作系统不会等待守护线程运行结束,gc就是一个守护线程。

一个线程在运行时出现了异常会怎么样:

  • 如果这个异常没有捕获的话,这个线程就会停止运行,如果这个线程的某个对象有监视器,这时就会释放。
    线程之间是如何共享数据的
    是通过共享对象来实现的,通过wait,notify,ntifyall,await,signal,signalall 进行唤醒和等待。
    sleep 和wait的区别

  • wait是object方法,sleep是thread的方法。

  • sleep阻塞一段时间后进入就绪态而wait就如等待队列,直到使用同一个锁对象的线程调用notify或notifyll方法才能将其唤醒。

  • wait只能在同步块或同步方法中使用,而sleep不需要

  • sleep不会释放锁,而wait会释放锁。
    线程的生命周期
    新生-》就绪-》运行-》阻塞-》消亡
    JAVA中的多线程