线程的五种状态:
1.new(新建):新建一个线程对象
有三种方法:
① 继承Thread类实现多线程,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例
- public class MyThread extends Thread {
- public void run() {
- System.out.println("MyThread.run()");
- }
- }
②实现Runnable接口方式实现多线程,如果自己的类已经extends另一个类,就无法直接extends Thread,此时,必须实现一个Runnable接口,如下:
- public class MyThread extends OtherClass implements Runnable {
- public void run() {
- System.out.println("MyThread.run()");
- }
- }
- MyThread myThread1 = new MyThread();
- MyThread myThread2 = new MyThread();
- myThread1.start();
- myThread2.start();
3.running(运行):可运行状态的的线程获得了cpu的时间片,执行程序代码
4.block(阻塞):阻塞状态是指线程因某种原因放弃了CPU限权,也让出timeslite,暂时停止运行,阻塞情况分三种:
1>等待阻塞:运行中的线程执行wait()方法,JVM会把该线程放入等待队列中
2>同步阻塞:运行中的线程在获取对象的同步锁时,若该同步锁被别的线程占用,JVM会把该线程放入锁池里
3>其他阻塞:执行sleep()方法
线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者
5.死亡状态(Dead):
有两个原因会导致线程死亡:
1> run方法正常退出而自然死亡,
2>一个未捕获的异常终止了run方法而使线程猝死。
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行 或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false
wait()与sleep方法的区别:
1.wait()来自Object类,sleep()来自Theard类
2.sleep没有释放锁,不会让出系统资源,它可以用时间指定使它自动唤醒过来,如果时间不到,只能用interrupt()强 行打断。
wait释放了锁,让出系统资源敏感词线程可用,等待敏感词线程调用notify/notifyAll唤醒等待池中的线程。
3.wait,notify,notifyAll只能在同步块或同步方法中使用
Synchronized(x){
x.wait();
x.notify();
}
sleep可以在任何地方使用
4.wait不用捕获异常,sleep必须捕获异常
线程安全和线程不安全:
非线程安全:当线程A获取一条数据,准备修改时,B线程进来了,并且把A这条数据删除了,这时A线程再执行就会报错。
线程安全:在A线程修改这条数据时,给它加一个锁(监视器),B进来时,发现数据已经上了锁,就会在线程池等待,等待A线程释放数据后,再对数据进行操作,这样防止脏数据产生。