线程的方法
1.1 启动一个线程
start() 与 run()
public class scence {
private static long fib(int n){
if(n < 2){
return n;
} else {
return fib(n-1) + fib(n-2);
}
}
private static class MyThread extends Thread{
private int n;
public MyThread(int n){
this.n = n;
}
@Override
public void run() {
long result = fib(n);
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args) {
int n = 6;
while(n > 0){
//来了客人,就找人来干活,启动的线程在完成真正的计算工作
Thread thread1 = new MyThread(n);
thread1.start();
long result = fib(n);
System.out.println(Thread.currentThread().getName());
n--;
}
}
}
运行结果;
- 调用 .start() 方法, 启动一个线程,线程之间是没有顺序的,是按CPU分配的时间片来回切换的。
public class scence {
private static long fib(int n){
if(n < 2){
return n;
} else {
return fib(n-1) + fib(n-2);
}
}
private static class MyThread extends Thread{
private int n;
public MyThread(int n){
this.n = n;
}
@Override
public void run() {
long result = fib(n);
System.out.println(Thread.currentThread().getName());
}
}
public static void main(String[] args) {
int n = 6;
while(n > 0){
//来了客人,就找人来干活,启动的线程在完成真正的计算工作
Thread thread1 = new MyThread(n);
thread1.run();
long result = fib(n);
System.out.println(Thread.currentThread().getName());
n--;
}
}
}
执行结果:
- 调用线程的run方法,就是普通的方法调用,虽然将代码封装到两个线程体中,但直接调用run()方法会导致线程未启动,主线程在干活。
run()方法用于封装线程的代码,具体要启动一个线程来运行线程体中的代码还是通过start()方法来实现,调用run()方法就是一种顺序编程不是并发编程。
1.2 中止一个线程
sleep() 和 interrupt()
thread.sleep(指定时间,单位为毫秒);
thread.interrupt();
sleep(long millis): 睡眠指定时间,程序暂停运行,睡眠期间会让出CPU的执行权,去执行其它线程,同时CPU也会监视睡眠的时间,一旦睡眠时间到就会立刻执行(因为睡眠过程中仍然保留着锁,有锁只要睡眠时间到就能立刻执行)。
- sleep(): 睡眠指定时间,即让程序暂停指定时间运行,时间到了会继续执行代码,如果时间未到就要醒需要使用interrupt()来随时唤醒
- interrupt(): 唤醒正在睡眠的程序,调用interrupt()方法,会使得sleep()方法抛出InterruptedException异常,当sleep()方法抛出异常就中断了sleep的方法,从而让程序继续运行下去
主动中止 vs 被动中止
A线程要B线程死
1)interrupt(); A 要 B停 —— 建议性中止
2)通过异常/通过B.isInterrupted/通过Thread.interrupted(检查自己)
B怎么就知道A要B死:
1) B正在睡眠(sleep/wait/join)
通知是以异常的形式给到:InterruputedException
2) B没有在睡眠
a. isInterrupted() 判断是否有人让我死
b. Thread.interrupted()
普通方法:interrupt() 通知线程停止(中断)
1)线程如果在休眠,会受到InterruptedException异常,状态位保持为false
2)线程如果没有在休眠,则状态位被修改为true
线程可以通过 普通方法 isInterrupted() 和静态**Thread.interrupted()**判断
1.isInterrupted()只获取当前状态,不会修改状态的值
2.Thread.interrupted() 获取当前状态,并且把状态修改为false
- isInterrupted()任何线程都可以调用,只要有该线程的Thread对象
- Thread.interrupted()查看当前线程的状态
线程什么时候退出,或者退不退出,由线程自行决定,建议性的通知
1.3 线程等待与线程唤醒
wait() 与 notify()
wait、notify和notifyAll方法是Object类的final native方法。所以这些方法不能被子类重写,Object类是所有类的超类,因此在程序中可以通过this或者super来调用this.wait(), super.wait()
- wait(): 导致线程进入等待阻塞状态,会一直等待直到它被其他线程通过notify()或者notifyAll唤醒。该方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。 wait(long timeout): 时间到了自动执行,类似于sleep(long millis)
- notify(): 该方法只能在同步方法或同步块内部调用, 随机选择一个(注意:只会通知一个)在该对象上调用wait方法的线程,解除其阻塞状态
notifyAll(): 唤醒所有的wait对象
注意:
Object.wait()和Object.notify()和Object.notifyall()必须写在synchronized方法内部或者synchronized块内部
让哪个对象等待wait就去通知notify哪个对象,不要让A对象等待,结果却去通知B对象,要操作同一个对象
1.4 等待退出
join()
- join():A线程等待B线程退出(停止)
能执行join()方法后面的语句,证明b线程已经结束,从run方法中退出 - join(timeout) A会在timeout时间内等B停止
1.5 yield()方法
yield()
暂停当前方法,释放自己拥有的CPU,线程进入就绪状态。
它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
但是执行了yield()方法,不会释放同步锁!
当释放了CPU,它和其他线程一起加入了就绪队列,拥有了抢占CPU的权利!