上一篇博客里面提到了,线程的执行并不是简单的顺序执行,当我们调用了start方法之后,它并不会立即执行run 方法,而是首先由系统为线程提供所必须的资源,在批处理系统中,还有等待队列问题,线程的调度在不同的处理器中可能使用不同的算法,不过我们只需要知道线程的执行是随机的这点就可以了。
三:线程睡眠
sleep(long)方法是使当前线程停止若干毫秒,线程由运行状态进入睡眠状态,当时间完成之后再次进入运行状态。
线程睡眠跟线程等待有很多的区别。
四:中断线程
线程中断只是为线程设置了一个中断标记,并没有中断线程运行,这个方法没有可以抛出的异常,一个线程被设置了中断标记之后仍可以运行,isalive()方法返回true,
线程中断的方法是interrupt();这个方法将设置线程的中断状态,但是值得注意的是这个线程并没有中断线程,而只是给线程的interrupt status 一个状态。
我们看下面一个很简单的代码
public class TestThread2 { public static void main(String[] args) { Thread2 thread2=new Thread2(); thread2.start(); } } class Thread2 extends Thread{ public void run(){ while(true){ System.out.println("开始执行……"); this.interrupt(); System.out.println("结束执行……"); } } }
这说明: interrupt中断的是线程的某一部分业务逻辑,前提是线程需要检查自己的中断状态(isInterrupted())。
在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 "
线程run方法会通过这个中断状态结束这个线程
五:线程中断
值得注意的是: 线程的可运行状态并不代表线程一定在运行(runnable != running ) 。 大家都知道:所有现代桌面和服务器操作系统都使用了抢占式的线程调度策略 。一旦线程开始执行,并不是总是保持持续运行状态的。当系统分给它的时间片(非常小的运行时间单位)用完以后,不管程序有没有执行完,线程被强制放弃CPU,进入就绪状态,直到下次被调度后开始继续执行。也就是说, Runnable可运行状态的线程处于两种可能的情况下:(1)占用CPU运行中,(2)等待调度的就绪状态。 这里要声明一下:处于等待调度的就绪状态线程和处于阻塞的线程是完全不同的。就绪的线程是因为时间片用完而放弃CPU,其随时都有可能再次获得CPU而运行,这一切取决于分时OS的线程调度策略。在很多操作系统的专业术语中,这种因时间片用完而被剥夺CPU的情况我们叫做线程中断。
线程中断是操作系统所作出的决定。
六:线程等待
wait()方法使你可以等待某个条件发生变化,而改变这个条件超出了当前方法的控制能力,你肯定不想在你的任务测试这个条件的同时,不断的使用空循环,这称为忙等待,通常在一种不良的CPU周期使用方式,因此wait()会在等待外部世界产生变化时将任务挂起,并且只有在notify() 或者notifyAll()发生时,即发生了某些感兴趣的事物,这个任务才会被唤醒并去检查所发生的变化,因此,线程等待提供了一种线程之间同步通信的策略。
再一个就是锁得问题,当我们对某些临界资源使用了同步锁synchronized之后,一个资源就只能被一个线程对象锁占有,而线程睡眠也就是使用sleep()方法不会释放资源,而线程等待就会放弃这些资源,这就意味着另一些任务将会得到这个锁,这在线程同步中至关重要。
有两种形式的wait()操作,第一种是接受毫秒参数的,但与sleep()相区别的有以下两点:
①:sleep不会释放资源
②:wait()有参数的那个方法必须得到其他线程使用notify()或者notifyAll()方法的唤醒。