Java线程
2017-10-05 12:39:10 27 举报
AI智能生成
Java线程知识
作者其他创作
大纲/内容
线程常用函数
1、线程睡眠:Thread.sleep(long millis)方法,使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为就绪(Runnable)状态。
Thread.Sleep(0)的作用,就是“触发操作系统立刻重新进行一次CPU竞争”。
2、线程让步:Thread.yield() 方法,暂停当前正在执行的线程对象,让当前运行线程回到可运行状态(非阻塞),以允许具有相同/高优先级的其他线程获得运行机会。
3、线程等待:Object类中的wait()方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。wait()在释放CPU的同时释放了对象锁的控制
4、线程唤醒:Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会任意选择唤醒其中一个线程。
被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。类似的方法还有一个notifyAll(),唤醒在此对象监视器上等待的所有线程。
5、线程加入:join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。
6、interrupt():向线程发送一个中断信号,让线程在无限等待时(如死锁时)能抛出异常,从而结束线程,但是如果你吃掉了这个异常,那么这个线程还是不会中断的!
wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。
7、其它:
isAlive(): 判断一个线程是否存活。
activeCount(): 程序中活跃的线程数。
enumerate(): 枚举程序中的线程。
currentThread(): 得到当前线程。
isDaemon(): 一个线程是否为守护线程。
setDaemon(): 设置一个线程为守护线程。(用户线程和守护线程的区别在于,是否等待主线程依赖于主线程结束而结束)
setName(): 为线程设置一个名称。
setPriority(): 设置一个线程的优先级,优先级高的线程会获得较多的运行机会。
线程同步
synchronized关键字两种作用域
某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(锁对象是当前实例);
synchronized(Obj){/*区块*/}表示对这个区块的资源互斥访问(锁对象是Obj)
某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。对类的所有对象实例起作用。(锁对象是当前类的Class对象)
synchronized关键字是不能继承:基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法
同步锁
Synchronized:只支持阻塞式的等待锁,synchronized的同步是不能Interrupt的
ReentrantLock:拥有Synchronized相同的并发性和内存语义,此外还多了锁投票,定时锁等候和中断锁等候。即可以选择阻塞,可以立即返回,可以设置等待时间,或者被中断。
a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁。
b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
c) tryLock(long timeout,TimeUnit unit),如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断。
性能:在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock还能维持常态。
线程数据传递
概念
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
多任务
主线程:JVM调用程序main()所产生的线程。
当前线程:这个是容易混淆的概念。一般指通过Thread.currentThread()来获取的线程。
前台线程(用户线程):是指接受后台线程服务的线程
后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。
用户线程和守护线程的区别在于,是否等待主线程依赖于主线程结束而结束。
可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程。
线程的实现
1.继承Thread类
2.实现Runnable接口(推荐)
实现Runnable接口比继承Thread类所具有的优势:
1):适合多个相同的程序代码的线程去处理同一个资源
2):可以避免java中的单继承的限制
3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
3、实现Callable接口并与Future、线程池结合使用。
FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值
线程状态转换
分支主题
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。(注意,sleep是不会释放持有的锁)
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
线程调度
分时调度:所有线程轮流获得CPU使用权,并平均分配每个线程占用CPU的时间
抢占式调度:根据线程的优先级别来获取CPU的使用权。JVM的线程调度模式采用了抢占式模式。
0 条评论
下一页