Java线程的状态转换

对于具体的几个状态解释,这里就不写了,比较容易理解。

对于线程的阻止,考虑一下三个方面,不考虑IO阻塞的情况:

l睡眠:

l等待

l因为需要一个对象的锁定而被阻塞。

一、为了让其他线程有机会执行,通常将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠。

try { Thread.sleep(123); } catch (InterruptedException e) { e.printStackTrace(); }


1、线程睡眠是帮助所有线程获得运行机会的最好方法。

2、线程睡眠到期自动苏醒,并返回到可运行状态,不是运行状态。sleep()中指定的时间是线程不会运行的最短时间。因此,sleep()方法不能保证该线程睡眠到期后就开始执行。

3、sleep()是静态方法,只能控制当前正在运行的线程。

二、线程的优先级和让步yield()

yield()方法的作用是:暂停当前正在执行的线程对象,并执行其他线程。

线程总是存在优先级,优先级范围在1~10之间。JVM线程调度程序是基于优先级的抢先调度机制。在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。注意:当设计多线程应用程序的时候,一定不要依赖于线程的优先级。因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。

当优先级相同时,jvm自由选择线程运行。这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。二是时间分片,为池内的每个线程提供均等的运行机会。

设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。可以通过setPriority(intnewPriority)更改线程的优先级。例如:

Thread t = new MyThread(); t.setPriority(8); t.start();




线程优先级为1~10之间的正整数

线程默认优先级是5,Thread类中有三个常量,定义线程优先级范围:

staticintMAX_PRIORITY
线程可以具有的最高优先级。
staticintMIN_PRIORITY
线程可以具有的最低优先级。
staticintNORM_PRIORITY
分配给线程的默认优先级。

三、Thread.yield()方法

Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。

yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。

四、Join()方法

Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。例如:

Thread t = new MyThread(); t.start(); t.join();




另外,join()方法还有带超时限制的重载版本。例如t.join(5000);则让线程等待5000毫秒,如果超过这个时间,则停止等待,变为可运行状态。

线程的合并的含义就是将几个并行线程的线程合并为一个单线程执行,应用场景是当一个线程必须等待另一个线程执行完毕才能执行时可以使用join方法。voidjoin()
等待该线程终止。
voidjoin(longmillis)
等待该线程终止的时间最长为millis毫秒。
voidjoin(longmillis,intnanos)
等待该线程终止的时间最长为millis毫秒+nanos纳秒。

线程的加入join()对线程栈导致的结果是线程栈发生了变化,当然这些变化都是瞬时的。下面给示意图:

五、多线程问题及处理

public class TicketsTest extends Thread{ Tickets t = null; String name=""; public TicketsTest(Tickets _t, String _name){ t = _t; name = _name; start(); } public void run(){ for(int i=0; i<5; i++){ synchronized (this){ System.out.println(name + "抢到了第" + t.getTicketNo() + "号票"); t.setTicketNo(t.getTicketNo()-1); } // t.saleTicket(name); try { Thread.sleep(20); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { Tickets t = new Tickets(10); TicketsTest p1 = new TicketsTest(t,"Tom"); TicketsTest p2 = new TicketsTest(t,"Mary"); System.out.println(p1.getState()); } } class Tickets{ private int tickets = 0; public Tickets(int ticketNumber){ tickets = ticketNumber; } public synchronized int getTicketNo(){ return tickets; } public synchronized void setTicketNo(int _tickets){ tickets = _tickets; } public synchronized void saleTicket(String name){ System.out.println(name + "抢到了第" + tickets + "号票"); tickets --; } }



synchronized 关键字是一个修饰符,可以修饰方法或代码块。作用是:对于同一个对象(不是一个类的不同对象),当多个线程同时调用该方法或代码块时,必须依次执行。