Java SE7 API - Thread: http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#yield%28%29
一、线程的简介
当JVM启动的时候, 通常会有一个独立的非守护线程(也就是类中的main方法所在的线程).JVM会继续运行,除非发生以下情况:
Runtime类的exit()方法被调用,并且安全管理者允许退出发生。
所有非守护线程都已经死了,不管是从run方法中返回的还是因为run方法中抛出了异常。
注意:当所有非守护线程都执行结束(包括主线程),那么守护线程也会退出。因为守护线程是无法脱离非守护线程而独自存在的。
二、创建线程有两种方式:
方法1:声明一个类作为Thread的子类(extends Thread),子类重写(override)Thread类的run()方法。子类的实例可以被分配和start。
//比如:该线程用来计算比指定起始值大的素数。 class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }
//以下代码用来创建和启动线程PrimeThread PrimeThread p = new PrimeThread(143); p.start();
方法2: 声明一个实现Runnable接口的类(implements Runnable),该类实现run()方法。该类的实例可以被分配,或者在创建Thread时作为一个参数,并且start.
class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }
PrimeRun p = new PrimeRun(143); new Thread(p).start();
三、Thread的方法:
static intactiveCount() | Returns an estimate of the number of active threads in the current thread‘s thread group and its subgroups. |
StringgetName() | Returns this thread‘s name. |
intgetPriority() | Returns this thread‘s priority. |
Thread.State getState() | Returns the state of this thread. |
booleanisAlive() | Tests if this thread is alive. |
booleanisDaemon() | Tests if this thread is a daemon thread. |
booleanisInterrupted() | Tests whether this thread has been interrupted. |
最常用的方法
void join() | Waits for this thread to die. |
void join(long millis) | Waits at most millis milliseconds for this thread to die. |
void join(long millis, int nanos) | Waits at most millis milliseconds plus nanos nanoseconds for this thread to die. |
void run() | If this thread was constructed using a separate Runnable run object, then that Runnable object‘s run method is called; otherwise, this method does nothing and returns. |
void setDaemon(boolean on) | Marks this thread as either a daemon thread or a user thread. |
static void sleep(long millis) | Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. |
static void sleep(long millis, int nanos) | Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds plus the specified number of nanoseconds, subject to the precision and accuracy of system timers and schedulers. |
void start() | Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread. |
static void yield() | A hint to the scheduler that the current thread is willing to yield its current use of a processor. |
从java.long.Object继承来的方法:
? ? ? ?
protected voidfinalize() | Called by the garbage collector on an object when garbage collection determines that there are no more references to the object. |
void notify() | Wakes up a single thread that is waiting on this object‘s monitor. |
void notifyAll() | Wakes up all threads that are waiting on this object‘s monitor. |
void wait() | Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. |
void wait(long timeout) | Causes the current thread to wait until either another thread invokes the notify() method or thenotifyAll() method for this object, or a specified amount of time has elapsed. |
void wait(long timeout, int nanos) | Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed. |
注意事项
1.sleep-wait-yield区别
sleep是Thread类中的一个静态方法,在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响,如果指定睡眠的时间到达,则从阻塞状态转变成就绪状态,等待运行。
yield只是使当前线程重新回到可执行状态,让其它同一优先级的线程先运行,所以执行yield()的线程有可能进入到可执行状态后马上又被执行。
wait是Object类中定义的方法,与notify/notifyAll()在一起成对使用,提供线程间的等待-通知机制。
2.使用wait-notify
(1).调用notify是随机的唤醒某一thread.而notifyAll则是唤醒所有等待的线程, 但只有一个线程可以在唤醒后lock object monitor,所以, notifyAll操作也是有利弊的.
(2).wait、notify、notifyAll必须在synchronized修饰的代码块中执行,否则会在运行的时候抛出IllegalMonitorStateException异常 .
(3).在循环语句wait的时候一定要设定循环的条件(while(flag))--这样能够避免wait开始之前,线程所需的条件已经被其他线程提供了却依然开始此线程wait导致的时间消耗。同时,这种办法还能够保证你的代码不被虚假的信息唤醒。
(4).总是要保证在调用notify和notifyAll之前,能够提供符合线程退出等待的条件。否则会出现即使线程接收到通知信息,却不能退出循环等待的情况。
3.join()方法
join方法是使当前线程阻塞,直到所引用的线程结束才激活.
4.synchronized关键字
synchronized有四种使用方式:
synchronized method(){}
synchronized (obj)
static synchronized method(){}
synchronized(classname.class)
前面两个使用的锁是对象monitor,后面两者使用的是类monitor,都可以实现互斥访问。
一个对象只有一个对象monitor,一个类也只有一个类monitor。静态方法使用类monitor进行同步,而普通方法则使用对象monitor进行同步。
五、线程的状态
线程有四种状态,任何一个线程肯定处于这四种状态中的一种:
1)产生(New):线程对象已经产生,但尚未被启动,所以无法执行。如通过new产生了一个线程对象后没对它调用start()函数之前。
2)可执行(Runnable):每个支持多线程的系统都有一个排程器,排程器会从线程池中选择一个线程并启动它。当一个线程处于可执行状态时,表示它可能正处于线程池中等待排排程器启动它;也可能它已正在执行。如执行了一个线程对象的start()方法后,线程就处于可执行状态,但显而易见的是此时线程不一定正在执行中。
3)死亡(Dead):当一个线程正常结束,它便处于死亡状态。如一个线程的run()函数执行完毕后线程就进入死亡状态。
4)停滞(Blocked):当一个线程处于停滞状态时,系统排程器就会忽略它,不对它进行排程。当处于停滞状态的线程重新回到可执行状态时,它有可能重新执行。如通过对一个线程调用wait()函数后,线程就进入停滞状态,只有当两次对该线程调用notify或notifyAll后它才能两次回到可执行状态。
代码示例:
public class Counter { public AtomicInteger inc = new AtomicInteger(); public void increase() { inc.getAndIncrement(); } public static void main(String[] args) throws InterruptedException { final Counter test = new Counter(); for (int i = 0; i < 10; i++) { Thread t = new Thread() { @Override public void run() { for (int j = 0; j < 10; j++) { test.increase(); System.out.println(Thread.currentThread().getName() + "----" + test.inc); } }; }; // t.setDaemon(true); t.start(); } while (Thread.activeCount() > 1)//保证前面的线程都执行完 { // Thread.yield(); // Thread.sleep(1); // System.out.println(Thread.currentThread().getName()+"-yield"); } System.out.println(test.inc); System.out.println("Thread.activeCount()="+Thread.activeCount()); } }
通过启用注释掉的部分可以得到不同的结果。