(一) 线程状态:
我们先讨论一下线程的几种状态:
java中Thrad.State总共有6中状态:
(1)New (新创建)
(2)Runnable (可运行)
(3)Bolcked (被阻塞)
(4)Waiting (等待)
(5)Timed Waiting (计时等待)
(6)Terminated (被终止)
这里先列出各个线程状态发生的条件,下面将会对每种状态进行详细解析和代码实例。
下面我们分别看一下线程的这6中状态分别出现在什么情况下。
(1)New (新创建)
当我们执行new Thread(target)时,jvm要为线程的运行做一些前期的准备工作,比如检查线程类是否已经被加载、解析和初始化过,接下来还要为对象分配空间并对空间
初始化零值,接下来还要对对象进行一些类的元数据信息、对象的GC分年代等的设置信息等。当完成这些准备工作时线程才能进入到下一个Runnable (可运行)状态。所以说
当业务需要频繁创建线程时,最好使用线程池,提高效率减轻JVM的压力。当然如果大量线程进行频繁上下文切换,此时多线程的效率会大打折扣。
public class ThreadTask {
public void concreteTask() {
System.out.println("线程开始执行");
long beginTime = System.currentTimeMillis();
System.out.println("线程正在执行具体任务");
// 等待5秒钟 模拟线程执行任务时间
while(System.currentTimeMillis() - beginTime < 5000) {}
System.out.println("线程执行完毕");
}
}
public class ThreadStateTest {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final ThreadTask tt = new ThreadTask();
//new Thread对象
Thread thread1 = new Thread(new Runnable(){
public void run() {
tt.concreteTask();
}
},"newThread1");
// 输出线程的状态
System.out.println(thread1.getState());
}
}
输出:NEW
(2)Runnable (可运行)
一旦调用线程的start()方法,线程就处于可运行状态。一个处于可运行状态的线程 可能正在运行 ,也可能正在等待操作系统为其分配cpu执行时间。我们将上面的代码添加一行代码thread1.start();
public class ThreadStateTest {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final ThreadTask tt = new ThreadTask();
//new Thread对象
Thread thread1 = new Thread(new Runnable(){
public void run() {
tt.concreteTask();
}
},"newThread1");
// 启动线程
thread1.start();
// 输出线程的状态
System.out.println(thread1.getState());
}
}
输出:
线程开始执行
线程正在执行具体任务
RUNNABLE
线程执行完毕
(3)Bolcked (被阻塞)
当一个线程试图获取内部对象锁(而不是java.util.cncurrent库中的锁),而该锁被其他线程持有,当所有其他线程释放锁,并且线程调度器运行
本线程持有锁时,该线程将变成非阻塞状态。
public class ThreadTask {
private Object lock = new Object();
public void concreteTask() {
synchronized(lock) {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
System.out.println(Thread.currentThread().getName()+"线程正在执行具体任务");
// 模拟线程耗时操作
long beginTime = System.currentTimeMillis();
while(System.currentTimeMillis() - beginTime < 5000) {}
System.out.println(Thread.currentThread().getName()+"线程执行完毕");
}
}
public void setFlag() {
synchronized(lock) {
System.out.println(Thread.currentThread().getName()+"has set true");
}
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final ThreadTask tt = new ThreadTask();
//new Thread对象
Thread thread1 = new Thread(new Runnable(){
public void run() {
tt.concreteTask();
}
},"newThread1");
Thread thread2 = new Thread(new Runnable(){
public void run() {
tt.setFlag();
}
},"newThread2");
thread1.start();
thread2.start();
Thread.sleep(1000);
// 输出线程的状态
System.out.println(thread1.getName() + ":" + thread1.getState());
System.out.println(thread2.getName() + ":" + thread2.getState());
}
}
输出:
newThread1线程开始执行
newThread1线程正在执行具体任务
newThread1:RUNNABLE
newThread2:BLOCKED
newThread1线程执行完毕
newThread2has set true
(4)Waiting (等待)
当线程等待另一个线程通知调度器一个条件时,这个线程就进入了等待状态。在调用Object.wait()方法或者Thread.join()方法,或等待java.util.concurrent库中的Lock或Condition时都会进入到等待状态。
调用join()方法
public class ThreadTask {
public void concreteTask() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
System.out.println(Thread.currentThread().getName()+"线程正在执行具体任务");
Thread thread2 = new Thread(new Runnable(){
public void run() {
System.out.println("newThread2 is running");
// 模拟线程耗时操作
long beginTime = System.currentTimeMillis();
while(System.currentTimeMillis() - beginTime < 5000) {}
System.out.println("newThread2 is stop");
}
},"newThread2");
thread2.start();
try {
thread2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"线程执行完毕");
}
}
public class ThreadStateTest {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final ThreadTask tt = new ThreadTask();
//new Thread对象
Thread thread1 = new Thread(new Runnable(){
public void run() {
tt.concreteTask();
}
},"newThread1");
thread1.start();
Thread.sleep(1000);
// 输出线程的状态
System.out.println(thread1.getName() + ":" + thread1.getState());
}
}
输出:
newThread1线程开始执行
newThread1线程正在执行具体任务
newThread2 is running
newThread1:WAITING
newThread2 is stop
newThread1线程执行完毕
等待java.util.concurrent库中的Lock时 进入等待状态
public class ThreadTask {
private Object lock = new Object();
private ReentrantLock reLock = new ReentrantLock();
public void concreteTask() {
reLock.lock();
try{
System.out.println(Thread.currentThread().getName()+"线程开始执行");
System.out.println(Thread.currentThread().getName()+"线程正在执行具体任务");
// 模拟线程耗时操作
long beginTime = System.currentTimeMillis();
while(System.currentTimeMillis() - beginTime < 5000) {}
System.out.println(Thread.currentThread().getName()+"线程执行完毕");
}finally {
reLock.unlock();
}
}
public void setFlag() {
reLock.lock();
try{
System.out.println(Thread.currentThread().getName()+"has set true");
}finally {
reLock.unlock();
}
}
}
public class ThreadStateTest {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final ThreadTask tt = new ThreadTask();
//new Thread对象
Thread thread1 = new Thread(new Runnable(){
public void run() {
tt.concreteTask();
}
},"newThread1");
Thread thread2 = new Thread(new Runnable(){
public void run() {
tt.setFlag();
}
},"newThread2");
thread1.start();
thread2.start();
Thread.sleep(1000);
// 输出线程的状态
System.out.println(thread1.getName() + ":" + thread1.getState());
System.out.println(thread2.getName() + ":" + thread2.getState());
}
}
输出:
newThread1线程开始执行
newThread1线程正在执行具体任务
newThread1:RUNNABLE
newThread2:WAITING
newThread1线程执行完毕
newThread2has set true
(5)Timed Waiting (计时等待)
同Waiting(等待)状态,有几个方法有超时参数,调用他们将进入计时状态。这一状态将一直保持到超时期满或者接收到适当通知。带有超时参数的方法有Thread.sleep() 、Object.wait()、Thread.join()、Lock.tryLock()、Condition.await()。
(6)Terminated (被终止)
线程因如下两个原因之一将被终止:
- run()方法正常退出而自然死亡
- 一个没有捕获的异常终止了run()方法而意外死亡