(一) 线程状态:
我们先讨论一下线程的几种状态:
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()方法而意外死亡