并发并不一定依赖多线程,(如php中常见的多进程并发) 但是java 中的并发和线程不开关系
Thread类的大部分方法都是native方法, native方法意味着,这个方法没有使用和平台无关的手段实现,或者是无法使用,当然也可能是为了执行效率
实现线程主要有三种方式
1. 内核线程实现,
2 ,使用用户线程实现
3.用户线程加轻量级进程混合实现
使用内核线程实现
内核线程就是直接由操作系统内核支持的线程,这种线程由内核来实现在每个线程上切换,内核通过操作操纵调度器多线程进行调度,并负责把线程的任务映射到各个处理器,每个内核线程可以视为内核的分身,支持多线程的内核叫做多线程内核
程序一般不会使用内核线程,而失去使用内核线程的一个高级接口,---轻量级进程,由于每个轻量级进程都有一个内核线程支持,因此只有先支持内核线程才能有轻量级进程,
由于内核线程的支持,每个线程都成了一个独立的调度单元,即使有一个轻量级的进程在系统中阻塞,也不会影响整个进程的工作,但是轻量级进程有局限性,
它是由内核线程实现的,因此各种线程的操作, 创建 同步, 都需要系统的调用,系统调用耗费的代价是比较高的
每一个轻量级进程都要一个内核线程的支持,因此轻量级进程要耗费一定的内核资源, 因此一个系统支持轻量级进程是有限的
用户使用用户线程实现
从广义上讲,一个线程不是内核线程就是用户线程,轻量级进程也属于用户线程,轻量级进程使用是在内核上,许多操作都要进城系统调用,效率会受到限制
而狭义上的用户线程指的是完全建立在用户空间的线程库上,系统内核不能感知线程存在的实现,用户线程的建立 同步 销毁 完全是在用户态中完成,不需要内核帮忙,如果程序实现的当, 这种线程不需要内核帮忙,因此这种效率是很低的可以支持规模更大的线程数量,这种进程与用户线程的关系是1:N的关系
这种实现的优势在于不需要内核线程的支援
不足在于没有系统内核的支援,由于操作系统把处理器资源分配到进程,哪诸如 线程阻塞如何处理,多处理器系统中如何将线程映射到其他处理器上,这类问题解决非常困难, java ruby 都是用过用户线程,但是都放弃了
使用用户线程加轻量级的进程混合使用
即存在用户线程,也存在轻量级进程,用户线程完全建立在用户的空间中,用户线程的创建销毁切换都是非常的廉价的,并且可以支持大规模的并发,而操作系统提供轻量级进程作为用户线程和内核线程的桥梁,这样可以使用内核提供的线程调度功能以及处理器映射,并且用户线程系统调用可以通过轻量级线程完成,这样降低了阻塞的风险,用户线程和轻量级线程未N:M 的关系
UNIX 操作系统,Solaris HP-UX 都提供N:M线程模型实现
Java线程实现
Sun JDK 他的windows 版本可Linux 版本都是一对一线程模型实现的,一条java线程就映射到一个轻量级线程中,因为windows 和linux 系统提供了线程模型是 1:1
但是在Solaris 平台中,由于操作系统的线程特性可以同时1:1 也可以多对多,因此Solaris 的jdk版本提供两个平台专有的虚拟机参数
-XX:+UseLWPSynchronization (默认值) -XX:+:USeBoundThreads 来明确规定虚拟机使用那种线程莫能行
java 线程调度
线程调度指系统为线程分配处理器使用权的过程,主要调度模式有两种,
1. 同式线调度
2。抢占式线程调度
如果式协同式调度多线程系统,线程的执行时间是有线程本身控制的, 线程把自己的工作执行完之后,要主动通知系统切换到另一个线程上去,协同式多线程的最大好处是实现简单, 弊端是 线程的执行时间不可控制,如果代码写的有问题一直阻塞,也不知道怎么了
如果使用抢占式多线程系统,那么每个线程将有系统来分配时间,线程的切换有系统来决定,java中的thread.yield() 可以让出执行时间,但是要获取执行时间的话线程没有办法,这样来说,一个线程阻塞也没问题, 从广义来讲,java使用抢占式线程调度,
虽然java 的线程调度是系统完成的,但是介意给一些线程分配点执行时间,java 设置了10 个现车优先级, 在两个线程都是ready的状态, 谁的优先级高谁先ready
不过优先级线程并不是多靠谱,因为java 的线程是通过映射到系统的原生线程实现的,所以线程的调度还是取决于操作系统,
windows 有一个优先级推动器 proiority boosting 哪个线程勤奋推他一把,让他更努力,所以有可能不会按照线程优先级
状态转换
java 语言定义了5线程状态,一个线程同一时间, 有且只能有一个状态
new 新建 : 创建线程但是没有启动
runable运行: funable包括了操作系统线程状态中的Running 和Ready 也就是处于此状态的先成功有可能正在执行,又有可能正在等待cpu为他分配执行时间
Waiting 无限期等待: 处于这种状态,线程永远不会被cpu分配执行时间,他们要等到其他的线程显式的唤醒,以下方法会让线程编程waiting状态
没有设置参数的 Object.wait()
没有设置Timeout参数的Thread.join()方法
LockSupport.park()方法
Time Waiting 有限日期等待 处于这种状态的线程不会被分配cpu执行时间 ,不过无须等待被其他线程显式的唤醒,在一定时间之后提供会自动唤醒他,
Thread.sleep()方法
。。。
阻塞(Blocked) :线程被阻塞,阻塞状态和等待状态区别是,阻塞状态在等待获取排他锁,整个事件将另外一个线程放弃锁的时候发生:而等待状态是等待一段时间或者唤醒动作的发生,