Java线程具有五种基本状态
新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread()。
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行。
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中。
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
public class MyCallable implements Callable {
//与run()方法不同的是,call()方法具有返回值
@Override
public Object call() throws Exception {
System.out.println("子线程正在计算:");
Thread.sleep(3000);
int sum=0;
for (int i = 0; i < 100; i++) {
sum+=i;
}
return sum;
}
}
package pers.hwh.thread;
import java.util.concurrent.*;
public class CallableTest {
public static void main(String[] args) {
Callable<Integer> myCallable = new MyCallable();
FutureTask<Integer> ft = new FutureTask<Integer>(myCallable);
Thread th = new Thread(ft);
th.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程正在执行");
try {
int sum = ft.get();
System.out.println("运行结果:sum="+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}//获取运行结果
System.out.println("所有任务执行完毕!");
public final void wait() throws InterruptedException
public final void wait(long timeout) throws InterruptedException
//指定等待时长,毫秒为单位
public final void wait(long timeout,int nanos) throws InterruptedException
//指定等待时长,毫秒+纳秒,timeout毫秒为单位,nanos纳秒为单位。时间精度更高
public final void notify()
notifyAll():唤醒在此同步锁对象上等待的所有线程,只有当前线程放弃对同步锁对象的锁定,才可能执行被唤醒的线程。
public final void notify()
在调用同一个对象的wait()方法和notify()方法的语句必须放在同步代码块中,并且同步代码块使用该对象的同步锁,否则在运行时则会抛出IllegalMonitorStateException异常
死锁
所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
也可以说是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
下面我们通过一些实例来说明死锁现象。
先看生活中的一个实例,两个人面对面过独木桥,甲和乙都已经在桥上走了一段距离,即占用了桥的资源,甲如果想通过独木桥的话,乙必须退出桥面让出桥的资源,让甲通过,但是乙不服,为什么让我先退出去,我还想先过去呢,于是就僵持不下,导致谁也过不了桥,这就是死锁。