Java-多线程
Posted 起风了1412
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-多线程相关的知识,希望对你有一定的参考价值。
多线程
- 什么是线程和进程?
进程是系统运行程序的基本单位,在Java中启动一个main函数就是启动一个JVM进程,main函数所在的线程叫主线程.
线程是一个比进程还小的执行单位,一个进程可以产生多个线程.
总结 : 进程间是互相独立的,线程间是共享进程的空间,所以线程会有并发问题.
JVM
- 运行时数据区域
线程私有 : 程序计数器,虚拟机栈,本地方法栈
线程共享 : 堆,方法区,直接内存
- 程序计数器
主要有2个作用:
1. 字节码解释器通过改变程序计数器来决定下一条指令,从而控制代码流程.
2. 多线程情况下,程序计数器用来记录当前线程执行的位置,当线程切换回来的时候可以继续之前的流程,所以程序计数器是私有的.
- Java 虚拟机栈
线程私有,Java内存大致可以分为堆区和栈区,栈区指的就是虚拟机栈,一般用来局部变量.
虚拟机栈可以出现的异常:
1. StackOverFlowError 当前线程请求栈的深度超过了虚拟机栈的最大深度.
2. OutOfMemoryError 当请求栈时,内存用完了且无法拓展时.
- 本地方法栈
线程私有,和虚拟机栈类似,区别是主要为 Native 方法服务.
- 堆
虚拟机管理的内存中最大的一块,线程共享.垃圾回收管理的主要区域,所以也成为GC堆.几乎所有的对象实例以及数组都在这分配内存.
- 方法区
线程共享,主要存放被虚拟机加载的类的信息,常量,静态变量等.
多线程
- 虚拟机栈和本地?法栈为什么是私有的?
这两个栈都是用来存放局部变量的,所以私有是为了防止别的线程访问到当前线程的局部变量.
- 说说并发与并?的区别?
- 并发:一段时间内,多个任务都在执行.(单位时间内,只有一个任务在执行.)
- 并行:单位时间内,多个任务同时执行.
- 什么是上下?切换?
当一个线程的时间片用完的时候就会变成就绪态,让其他线程使用,这个过程就是一次上下文切换.
- 什么是线程死锁?如何避免死锁?
线程1拥有资源A,线程2拥有资源B,此时线程1去申请资源B,由于B已经被线程2持有,所以线程1进入阻塞等待状态,并且不会主动释放所持有的资源A,这就叫死锁.
- 如何避免线程死锁?
产生死锁的条件:
- 互斥条件 : 该资源某一时刻只能被一个线程所持有.
- 请求与保持条件 : 进程因为请求资源而阻塞时,已持有的资源保持不放.
- 不剥夺条件 : 线程所持有的资源除非自己主动释放,否则一直持有,其他线程无法强行剥夺.
- 循环等待条件 : 多个线程形成一个资源循环等待环.
避免死锁,破坏条件:
- 破坏互斥条件 : 无法破坏,因为锁的本意就是让资源在一段时间内只能被一个线程所持有.
- 破坏请求与保持条件 : 一次性申请所有资源.
- 破坏不剥夺条件 : 当线程申请资源失败的时候,释放自己所持有的资源.
- 破坏循环等待条件 : 按顺序申请资源.
- sleep() ?法和 wait() ?法区别?
- sleep不会释放锁,wait会释放锁.
- 都可以暂停线程.
- wait调用后不会自动苏醒,需要别的线程调用notify()唤醒,但是可以使用wait(long timeout)超时自动苏醒.
- 为什么我们调? start() ?法时会执? run() ?法,为什么我们不能直接调? run() ?法?
调用start()时,会启动一个线程,当线程获得CPU时间时执行run()里面的内容;直接调用run(),会把run()当初main()下的一个普通方法去执行.
- synchronized关键字最主要的三种使??式?
- 修饰实例(普通)方法 : 给当前实例对象加锁.
//假设 Demo 类的 demo() 被 synchronized 修饰
//例1 : 线程1,2抢占的是同一把锁,只能有一个线程持有.
public static void main(String[] args) {
Demo demo = new Demo();
Thread thread1 = new Thread(new MyThread(demo));
Thread thread2 = new Thread(new MyThread(demo));
thread1.start();
thread2.start();
}
//例2 : 线程1,2抢占的是两把锁
public static void main(String[] args) {
Demo demo1 = new Demo();
Demo demo2 = new Demo();
Thread thread1 = new Thread(new MyThread(demo1));
Thread thread2 = new Thread(new MyThread(demo2));
thread1.start();
thread2.start();
}
- 修饰静态方法 : 给当前类加锁,作用于类的所有实例对象.
修饰静态方法后上面不论是例1还是例2都是抢占一个锁.
- 修饰代码块 : 给指定对象加锁.
-
synchronized 关键字的底层原理?
synchronized 关键字属于JVM层面. 通过查看字节码信息可以发现, synchronized 锁定代码的前后分别是 monitorenter 和 monitorexit ;当执行 monitorenter 时,线程去尝试获取锁(monitor,它存在于每个Java对象的头部, 所以Java对象都可以作为锁.),当计数器为0时获取成功,然后将计数器加1;执行 monitorexit 时,计数器减一. 如果锁获取失败,那么当前线程就一直等待,直到锁被另一个线程释放.
以上是关于Java-多线程的主要内容,如果未能解决你的问题,请参考以下文章