Java学习疑点(4)--线程的六个状态以及其安全性问题的个例解析

原创 2013年07月07日 13:17:13

Thread States

Threads can be in one of six states:

  •  New
  •  Runnable
  •  Blocked
  •  Waiting
  •  Timed waiting
  •  Terminated

Each of these states is explained in the sections that follow.

To determine the current states of a threads, simply call the getState method.

 

New Threads

When you create a thread with the new operator--the thread is not yet running.This means that it is in thenewstate.When a thread is in the new state, the programe has not started executing code inside of it.A certain amount of bookkeeping needs to be done before a thread can run.

 

Runnable Threads

Once you invoke the start method, the thread is in the runnable state.A runnable thread may or may not actually be running.It is up to the operating system to give the thread time to run.(The Java specification doen not call this a separate state, though. A running thread is still in the runnable state.)

Once a thread is running,  it doesn't necessarily keep running.In fact, it is desirable if running threads occasionally pause so that other threads have a chance to run. The details of thread scheduling systems give each runnable thread a slice of time to perform its task.When that slice of time is  exhausted, the operating system preempts the thread and gives another thread an opportunity to work.

All modern desktop and server operating systems use preemptive scheduling. However, small devices such as cell phones may use cooperating scheduling. In such a device, a thread loses control only when it calls the yield method,  or it is blocked or waiting.

On a machine with multiple processors, each  processor can run a thread, and you can hava multiple threads run in parallel. Of course, if there are more threads than processors, the scheduler still has to do time-slicing.

Always keep in mind that a runnable thread may or may ont be running at any given time.(This is why the states is called "runnable" and not "running.")

 

Blocked and Waiting Threads

When a thread is blocked ot waiting, it is temporarily inactive. It doesn't execute any code and it consumes mininal resources. It is up to the thread scheduler to reactivate it.

The details depend on  how the inactive state was reached.

  • When the thread tries to acquire an intrinsic object lock(buy not a Lock in the java.util.concurrent library) that is currently held by another thread, it becomes blocked. The thread becomes unblocked when all other threads have relinquished the lock and the thread scheduler has allowed this thread to hold it.
  • When the thread waits for another thread to notify the scheduler of a condition, it enters the waiting states. This happens by calling the object.wait or Thread.join method, or by waiting for a Lock or Condition in the java.util.concurrent Library. In practice, the differece between the blocked and waiting state is not significant.
  • Several methods have a timeout parameter. Calling them causes the thread to enter the timed waiting state. This state persists either until the timeout expired or the appropriate notification has been received. Methods with timeout include Thread.sleep and the timed versions of Object.wait, Thread.join, Lock.tryLock, and Condition.await.

Terminated Threads

A thread is terminated for one of two reasons:

  • It dies a natural death because the run method exits normally.
  • It dies abruptly because an uncaught exception terminates the run method.

In particular, you can kill a thread by invoking its stop method. That method throws a ThreadDeath error object that kills the thread. However, the stop method is deprecated, and you should never call is in yout own code.

以上内容摘自<Java核心技术卷I: 基础知识>(第8版)

 

       一个线程在启动之后, 未必一直处于运行状态, 它什么时候处于运行状态取决于操作系统, 在某一时刻, 它可能处于非运行状态. 在程序逻辑中对此要特别小心, 防止因此产生错误. 例如, 如果你期望你的线程检测到某个具体时间点执行一个操作, 那么你的这个期望就有可能出现问题了, 因为也许在这个时间点到来的这个时刻, 刚好这个线程处于非运行状态, 此时你就无法捕捉这个时间点, 最终错过了执行操作的时机.

           另外, 不要把这点与线程中调用sleep相混淆, 在线程中调用sleep之后, 线程就进入另一种状态, 而不是runnable状态. 我们在此处所说的是线程处于runnable状态时有可能处于非运行状态. 提到sleep方法, 还有一点要注意, 线程执行sleep(睡眠)到期自动苏醒并返回runnable状态后, 未必能够立即得到运行的机会. 因此, sleep方法中指定的时间是线程不会运行的最短时间, sleep方法不能保证该线程睡眠到期后就立即开始执行.

 

下面引用一个简单典型的例子说明多线程可能存在的安全问题:

public void run() {
	while(true) {
		if(sum == 0) {
			sum++;
		}
                ......
	}
        ......
}
sum为多线程共享的变量


 

当上面这段代码由多个线程共同执行时, 当sum为0时, 线程1执行了if判断但是还未执行sum++时, 操作系统令其进入非运行状态而由线程2进入运行状态, 这时sum任然为0, 线程1和2就执行了sum++两次, 从而导致安全问题产生.

怎样避免这种问题呢?方法很多, 这里我们用同步代码块来做:

public void run() {
	while(true) {
		synchronized(this) {
			if(sum == 0) {
				sum++;
			}
		}
		......
	}
	......
}

我们将if代码块使用同步, 如此当线程1开始执行代码块中的内容但还未结束时, 其他线程就无法进入这片代码块中, 也就是保证了synchronized这块内容只允许一个线程执行, 当该线程没有执行完时, 其他线程是无法获得执行资格的. 从而保证了上述安全问题不会发生.

在使用多线程时, 一定要注意操作线程之间共享内容时可能会引发的安全问题.

 

《Java并发编程实践》笔记5——线程活跃性问题及其解决方法

1.死锁的定义及发生条件: 死锁就像是两个人过独木桥,在桥中间碰到了,谁也不想让步,结果谁也无法通过。 线程A占有锁L时想要获得锁M,而线程B占有锁M并尝试获得锁L,两个线程将永远等待下去,这种情...
  • chjttony
  • chjttony
  • 2015年06月26日 16:41
  • 2930

java 线程安全和不安全

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。(Vector,HashTa...
  • mccand1234
  • mccand1234
  • 2016年07月24日 11:30
  • 2800

SpringMVC的Controller单例线程安全问题

这个文章验证了单例http://blog.csdn.net/darkdragonking/article/details/52367186 每个请求都会分配一个线程处理请求http://www.cn...
  • maoyeqiu
  • maoyeqiu
  • 2017年03月09日 20:08
  • 1153

java 线程有几种状态

在java中,线程通常有五种状态,创建,就绪,运行、阻塞和死亡状态。   第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。   第二是就绪状态。当调...
  • L398724306
  • L398724306
  • 2015年04月29日 08:35
  • 1769

根据java内存模型理解并发出现的问题

原子性1、某些读写共享变量的操作如果不是原子操作,多线程并发的情况下会出现并发问题。 2、原子性实现了多个线程并发访问某段代码的时候,使这些线程能够有序访问。因为实现原子操作代码的一旦被执行,就不能...
  • bh_xiaoxinba
  • bh_xiaoxinba
  • 2016年09月12日 22:21
  • 223

java线程的六个状态

在java的API中线程的六个状态: 1.新建状态(new):使用new创建一...
  • qq_39396275
  • qq_39396275
  • 2017年07月14日 23:58
  • 95

并发编程(4)线程的生命周期及基本状态

线程从创建到最终的消亡,要经历若干个状态,一般来说,线程包括以下这几个状态:新建(new),可运行(runnable),运行(running),阻塞(blocked),死亡(dead)。 先来一张经典...
  • u012170724
  • u012170724
  • 2016年03月24日 16:04
  • 462

线程的四种状态

 1. 新状态:线程已被创建但尚未执行(start() 尚未被调用)。2. 可执行状态:线程可以执行,虽然不一定正在执行。CPU 时间随时可能被分配给该线程,从而使得它执行。3. 死亡状态:正常情况下...
  • wangjun_pfc
  • wangjun_pfc
  • 2007年11月11日 01:24
  • 3671

java多线程高并发线程安全问题

在抢购之类的业务处理时,会出现超发之类的线程安全问题。 我个人想到的解决方法如下: 采用数据库锁,悲观锁有效率低下问题,所以我推荐乐观锁,虽然会增大CPU开销,很多服务和软件都支持乐观锁,如Redi...
  • qq_36823916
  • qq_36823916
  • 2017年06月26日 11:40
  • 414

applet跨域访问的安全性问题

最近在用jasperreport做报表时,出现一个问题,项目发布在内网时,打印一切正常,但是发布到外网,而且使用域名访问时,总是报拒绝访问的错误: java.security.AccessContr...
  • mhmyqn
  • mhmyqn
  • 2012年12月30日 16:21
  • 4679
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java学习疑点(4)--线程的六个状态以及其安全性问题的个例解析
举报原因:
原因补充:

(最多只允许输入30个字)