一、Java线程的周期:
1. 线程有五个基本状态描述
New: 新建线程(创建一个线程,但是没有任何可运行的实体)
Runnable 线程就绪(将程序变量实体放入线程中,可执行状态)
Running 运行(运行放入的程序)
Blocked 阻塞(程序暂停,等待自动唤醒或者被动唤醒)
Dead 结束(程序运行结束或者异常退出)
2.线程有五个基本状态的转换
1)yield()方法 使当前线程用运行状态进入就绪状态(可执行状态),不会释放“锁”;sleep(long millis)当前线程进入阻塞状态,睡眠millis毫秒后,进入就绪状态,不会释放“锁”
2)t.join() t线程先执行
3)interrupt() 将解除线程的阻塞状态
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while(true){
if(Thread.currentThread().isInterrupted()){
System.out.println("Someone interrupted me.");
return;
} else{
System.out.println("Thread is Going...");
}
}
}
});
System.out.println("mainmainmain");
t.start();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
System.out.println("main-----main线程运行结束结束");
4) notifyAll()、notify()、wait()必须在同步方法中;
wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。wait()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronized block中进行调用,如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常
总结:wait()和notify(),notifyAll()是Object类的方法,sleep()和yield()是Thread类的方法;
备注:wait() 与notify()/notifyAll()
这三个方法都是Object的方法,并不是线程的方法!
wait():释放占有的对象锁,线程进入等待池,释放cpu,而其他正在等待的线程即可抢占此锁,获得锁的线程即可运行程序。而sleep()不同的是,线程调用此方法后,会休眠一段时间,休眠期间,会暂时释放cpu,但并不释放对象锁。也就是说,在休眠期间,其他线程依然无法进入此代码内部。休眠结束,线程重新获得cpu,执行代码。wait()和sleep()最大的不同在于wait()会释放对象锁,而sleep()不会!
notify(): 该方法会唤醒因为调用对象的wait()而等待的线程,其实就是对对象锁的唤醒,从而使得wait()的线程可以有机会获取对象锁。调用notify()后,并不会立即释放锁,而是继续执行当前代码,直到synchronized中的代码全部执行完毕,才会释放对象锁。JVM则会在等待的线程中调度一个线程去获得对象锁,执行代码。需要注意的是,wait()和notify()必须在synchronized代码块中调用。(wait会释放锁,notify 不会是否锁)
notifyAll()则是唤醒所有等待的线程。
二、Java线程的实现
1.继承Thread 类 重写run方法
2.实现Runnable
3.使用Callable 和Future 接口创建线程(线程中可以有返回值)