并发编程学习总结(二) : 详解 线程的6种不同状态

(一) 线程状态:

我们先讨论一下线程的几种状态:

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 (被终止)

线程因如下两个原因之一将被终止:

  1. run()方法正常退出而自然死亡
  2. 一个没有捕获的异常终止了run()方法而意外死亡
时间: 2024-08-07 05:03:14

并发编程学习总结(二) : 详解 线程的6种不同状态的相关文章

Java并发编程学习笔记(一)线程安全性 1

什么是线程安全性: 要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问."共享"意味着变量可以由多个线程同时访问,而"可变"则意味着变量的值在其生命周期内可以发生变化. 一个对象是否需要线程安全的,取决于他是否被多个线程访问.这指的是在程序中访问对象的方式,而不是对象要实现的功能.要使得对象时线程安全的,需要采用同步机制来协同对对象可变状态的访问.如果无法实现协同,那么可能导致数据破坏以及其他不该出现的结果. 如果当多个线程访

Java并发编程之---Lock框架详解

Java 并发开发:Lock 框架详解 摘要: 我们已经知道,synchronized 是Java的关键字,是Java的内置特性,在JVM层面实现了对临界资源的同步互斥访问,但 synchronized 粒度有些大,在处理实际问题时存在诸多局限性,比如响应中断等.Lock 提供了比 synchronized更广泛的锁操作,它能以更优雅的方式处理线程同步问题.本文以synchronized与Lock的对比为切入点,对Java中的Lock框架的枝干部分进行了详细介绍,最后给出了锁的一些相关概念. 一

Java并发编程(十二):线程池的使用(转载)

本文转载自:http://www.cnblogs.com/dolphin0520/p/3932921.html 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间. 那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务? 在Java中可以通过线程池来达到这样的效果.

Java并发编程学习笔记(一)——线程安全性

1.当多个线程访问某个状态变量并且其中有一个献策灰姑娘执行写入操作时,必须采用同步机制来协同这些线程对变量的访问.Java中的主要同步机制是关键字synchronized,他提供了一种独占的加锁方式. 2.在任何情况下,只有当类中仅包含自己的状态时,线程安全类才是有意义的. 3.当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些献策灰姑娘讲如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的. 4.无状态对象一定是线程安全的

并发编程(壹):创建线程的三种方式及其对比

创建线程的三种方式及其对比 1. 继承 Thread类 (1). 继承Thread类.并重写run()方法,该方法无参数,无返回值: (2). 创建子类实例,并实例化对象: (3). 通过start()方法启动,注意:不是通过run()方法启动. public class ThreadDemo extends Thread{ public void run(){ System.out.println("继承Thread创建线程的."); } } public class ThreadA

C++11并发编程-条件变量(condition_variable)详解

<condition_variable >头文件主要包含了与条件变量相关的类和函数.相关的类包括 std::condition_variable和 std::condition_variable_any,还有枚举类型std::cv_status.另外还包括函数 std::notify_all_at_thread_exit(),下面分别介绍一下以上几种类型. std::condition_variable 类介绍 std::condition_variable是条件变量,更多有关条件变量的定义参

Java并发编程之栅栏(CyclicBarrier)详解

栅栏类似闭锁,但是它们是有区别的. 闭锁用来等待事件,而栅栏用于等待其他线程.什么意思呢?就是说闭锁用来等待的事件就是countDown事件,只有该countDown事件执行后所有之前在等待的线程才有可能继续执行;而栅栏没有类似countDown事件控制线程的执行,只有线程的await方法能控制等待的线程执行. CyclicBarrier强调的是n个线程,大家相互等待,只要有一个没完成,所有人都得等着. 场景分析:10个人去春游,规定达到一个地点后才能继续前行.代码如下 import java.

Java并发编程系列之Semaphore详解

简单介绍 我们以饭店为例,假设饭店只有三个座位,一开始三个座位都是空的.这时如果同时来了三个客人,服务员人允许他们进去用餐,然后对外说暂无座位.后来的客人必须在门口等待,直到有客人离开.这时,如果有一个客人离开,服务员告诉客人,可以进来用餐,如果又有客人离开,则又可以进来客人用餐,如此往复.在这个饭店中,座位是公共资源,每个人好比一个线程,服务员起的就是信号量的作用.信号量是一个非负整数,表示了当前公共资源的可用数目(在上面的例子中可以用空闲的座位类比信号量),当一个线程要使用公共资源时(在上面

Java并发编程学习笔记

Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现Runnable接口并编写run方法,使得该任务可以执行你的命令.   class MyTask implements Runnable {    private String mName;     public MyTask(String name) {    mName = name;   }