Java SE7 API - Thread:html
http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#yield%28%29java
參考資料:http://blog.csdn.net/lqqmisslll/article/details/54208491程序員
1、線程的簡介api
當JVM啓動的時候, 一般會有一個獨立的非守護線程(也就是類中的main方法所在的線程).JVM會繼續運行,除非發生如下狀況:安全
Runtime類的exit()方法被調用,而且安全管理者容許退出發生。多線程
全部非守護線程都已經死了,不論是從run方法中返回的仍是由於run方法中拋出了異常。併發
注意:當全部非守護線程都執行結束(包括主線程),那麼守護線程也會退出。由於守護線程是沒法脫離非守護線程而獨自存在的。oracle
2、建立線程有兩種方式:app
方法1:聲明一個類做爲Thread的子類(extends Thread),子類重寫(override)Thread類的run()方法。子類的實例能夠被分配和start。 jvm
//好比:該線程用來計算比指定起始值大的素數。 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與實現Runnable的區別:
實現 Runnable 大多數狀況下是比繼承 Thread 更好的方法。
1. Java 只支持單繼承,因此你繼承了 Thread 的話,其餘的類你就不能繼承了。
2. 若是實現 Runnable 接口,多線程能夠直接將你的工做併發處理(直接使用 start)。而繼承 Thread 不能直接進行多線程工做,你得爲你的每一部分工做都定義一個線程。
3. 其餘的一些API,接口都是 Runnable 類型的。好比 Java 內置的線程池 API ExcutorService 等。
3、線程的狀態
線程有四種狀態,任何一個線程確定處於這四種狀態中的一種:
1)產生(New):線程對象已經產生,但還沒有被啓動,因此沒法執行。如經過new產生了一個線程對象後沒對它調用start()函數以前。
2)可執行(Runnable):每一個支持多線程的系統都有一個排程器,排程器會從線程池中選擇一個線程並啓動它。當一個線程處於可執行狀態時,表示它可能正處於線程池中等待排排程器啓動它;也可能它已正在執行。如執行了一個線程對象的start()方法後,線程就處於可執行狀態,但顯而易見的是此時線程不必定正在執行中。
3)停滯(Blocked):當一個線程處於停滯狀態時,系統排程器就會忽略它,不對它進行排程。當處於停滯狀態的線程從新回到可執行狀態時,它有可能從新執行。如經過對一個線程調用wait()函數後,線程就進入停滯狀態,只有當兩次對該線程調用notify或notifyAll後它才能兩次回到可執行狀態。
4)死亡(Dead):當一個線程正常結束,它便處於死亡狀態。如一個線程的run()函數執行完畢後線程就進入死亡狀態。
3、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. |
void interrupt() | Interrupts this thread. If this thread is blocked in an invocation of the If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a If this thread is blocked in a If none of the previous conditions hold then this thread's interrupt status will be set. |
從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、實現線程同步的方法
1.有synchronized關鍵字的同步方法
synchronized有四種使用方式:
synchronized method(){}
synchronized (obj)
static synchronized method(){}
synchronized(classname.class)
前面兩個使用的鎖是對象monitor,後面二者使用的是類monitor,均可以實現互斥訪問。
一個對象只有一個對象monitor,一個類也只有一個類monitor。靜態方法使用類monitor進行同步,而普通方法則使用對象monitor進行同步。
2.使用lock()與unlock()之間的同步塊。
代碼示例:
1.經過setDaemon(true)將鮮橙設置爲守護線程,以及守護線程的特色。
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()); } }
經過啓用註釋掉的部分能夠獲得不一樣的結果。
2. 使用join()控制線程執行順序:http://my.oschina.net/liuyuanyuangogo/blog/315927
3. 使用interrupt()方法控制線程的中止:
/** * * @author Yuanyuan * 終止線程的方法 * stop()方法不安全,已啓用。 * 如何終止線程? * 終止線程的方法只有一個,就是讓run()方法運行結束. * * 開啓多線程運行時,運行代碼一般是循環結構。 * 只要控制住循環,就可讓run方法結束,也就是該線程結束。(一般會用一個標記變量來控制) * * 特殊狀況, * 當線程處於凍結狀態。就不會讀取到標記,那線程就沒法結束。 * * 當沒有指定的方式讓凍結的線程回覆到運行狀態,這是須要對凍結進行清除。 * 強制讓線程恢復到運行中來,這樣就能夠操做標記讓線程結束。 * Thread類提供了方法interrupt() * */ class StopThread extends Thread { private boolean flag = true; @Override public synchronized void run() { while(flag) { try { this.wait(); } catch (InterruptedException ex) { System.out.println(Thread.currentThread().getName()+"---Exception"); flag = false; } } System.out.println(Thread.currentThread().getName()+"---run"); } } public class ThreadDemo { public static void main(String[] args) { Thread t1 = new StopThread(); Thread t2 = new StopThread(); t1.start(); t2.start(); for(int i=0;i<10;i++) { if(i==5) { t1.interrupt();// t2.interrupt(); } System.out.println(Thread.currentThread().getName()+"---"+i); } } }
舉例說明Thread與Runnable的區別:
(如下轉自:http://mars914.iteye.com/blog/1508429)
在實際應用中,咱們常常用到多線程,如車站的售票系統,車站的各個售票口至關於各個線程。當咱們作這個系統的時候可能會想到兩種方式來實現,繼承Thread類或實現Runnable接口,如今看一下這兩種方式實現的兩種結果。
package com.threadtest; class MyThread extends Thread { private int ticket = 10; private String name; public MyThread(String name) { this.name =name; } public void run() { for(int i =0;i<500;i++) { if(this.ticket>0) { System.out.println(this.name+"賣票---->"+(this.ticket--)); } } } } public class ThreadDemo { public static void main(String[] args) { MyThread mt1= new MyThread("一號窗口"); MyThread mt2= new MyThread("二號窗口"); MyThread mt3= new MyThread("三號窗口"); mt1.start(); mt2.start(); mt3.start(); } }
運行結果以下:
一號窗口賣票---->10 一號窗口賣票---->9 二號窗口賣票---->10 一號窗口賣票---->8 一號窗口賣票---->7 一號窗口賣票---->6 三號窗口賣票---->10 一號窗口賣票---->5 一號窗口賣票---->4 一號窗口賣票---->3 一號窗口賣票---->2 一號窗口賣票---->1 二號窗口賣票---->9 二號窗口賣票---->8 三號窗口賣票---->9 三號窗口賣票---->8 三號窗口賣票---->7 三號窗口賣票---->6 三號窗口賣票---->5 三號窗口賣票---->4 三號窗口賣票---->3 三號窗口賣票---->2 三號窗口賣票---->1 二號窗口賣票---->7 二號窗口賣票---->6 二號窗口賣票---->5 二號窗口賣票---->4 二號窗口賣票---->3 二號窗口賣票---->2 二號窗口賣票---->1
經過實現Runnable接口的代碼以下:
class MyThread1 implements Runnable{ private int ticket =10; private String name; public void run(){ for(int i =0;i<500;i++){ if(this.ticket>0){ System.out.println(Thread.currentThread().getName() +"賣票---->"+(this.ticket--)); } } } } public class RunnableDemo { public static void main(String[] args) { // TODO Auto-generated method stub //設計三個線程 MyThread1 mt = new MyThread1(); Thread t1 = new Thread(mt,"一號窗口"); Thread t2 = new Thread(mt,"二號窗口"); Thread t3 = new Thread(mt,"三號窗口"); // MyThread1 mt2 = new MyThread1(); // MyThread1 mt3 = new MyThread1(); t1.start(); t2.start(); t3.start(); } }
運行結果以下:
一號窗口賣票---->10 三號窗口賣票---->9 三號窗口賣票---->7 三號窗口賣票---->5 三號窗口賣票---->4 三號窗口賣票---->3 三號窗口賣票---->2 三號窗口賣票---->1 一號窗口賣票---->8 二號窗口賣票---->6
爲何會出現這種結果吶。咱們不妨作個比喻,其實剛的程序,
繼承Thread類的,咱們至關於拿出三件事即三個賣票10張的任務分別分給三個窗口,他們各作各的事各賣各的票各完成各的任務,由於MyThread繼承Thread類,因此在new MyThread的時候在建立三個對象的同時建立了三個線程;
實現Runnable的, 至關因而拿出一個賣票10張得任務給三我的去共同完成,new MyThread至關於建立一個任務,而後實例化三個Thread,建立三個線程即安排三個窗口去執行。
用圖表示以下:
在咱們剛接觸的時候可能會迷糊繼承Thread類和實現Runnable接口實現多線程,其實在接觸後咱們會發現這徹底是兩個不一樣的實現多線程,一個是多個線程分別完成本身的任務,一個是多個線程共同完成一個任務。
其實在實現一個任務用多個線程來作也能夠用繼承Thread類來實現只是比較麻煩,通常咱們用實現Runnable接口來實現,簡潔明瞭。
大多數狀況下,若是隻想重寫 run() 方法,而不重寫其餘 Thread 方法,那麼應使用 Runnable 接口。這很重要,由於除非程序員打算修改或加強類的基本行爲,不然不該爲該類(Thread)建立子類。
Difference between Thread vs Runnable interface in Java
Thread vs Runnable in Java is always been a confusing decision for beginner s in java. Thread in Java seems easy in comparison of Runnable because you just deal with one class java.lang.Thread while in case of using Runnable to implement Thread you need to deal with both Thread and Runnable two classes. though decision of using Runnable or Thread should be taken considering differences between Runnable and Thread and pros and cons of both approaches. This is also a very popular thread interview questions and most of interviewer are really interested to know what is your point of view while choosing Thread vs Runnable or opposite. In this java article we will try to point out some differences between Thread and Runnable in Java which will help you to take an informed decision.
Thread vs Runnable in Java
Here are some of my thoughts on whether I should use Thread or Runnable for implementing task in Java, though you have another choice as " Callable " for implementing thread which we will discuss later.
1) Java doesn't support multiple inheritance , which means you can only extend one class in Java so on c e you extend ed Thread class you lost your chance and can not extend or inherit another class in Java .
2) In Object oriented programming extending a class generally means adding new functionality, modifying or improving behaviors. If we are not making any modification on Thread than use Runnable interface instead.
3) Runnable interface represent a Task which can be executed by either plain Thread or Executors or any other means. so logical separation of Task as Runnable than Thread is good design decision.
4) Separating task as Runnable means we can reuse the task and also has liberty to execute it from different means. since you can not restart a Thread once it completes. again Runnable vs Thread for task, Runnable is winner.
5) Java designer recognizes this and that's why Executors accept Runnable as Task and they have worker thread which executes those task.
6) Inheriting all Thread methods are additional overhead just for representing a Task which can can be done easily with Runnable.
These were some of notable difference between Thread and Runnable in Java, if you know any other differences on Thread vs Runnable than please share it via comments. I personally use Runnable over Thread for this scenario and recommends to use Runnable or Callable interface based on your requirement.
Some more Java Tutorials you may like
Why Wait and Notify in Java is called from Synchronized context
Difference between Comparator and Comparable in Java
Difference between Wait, Sleep and yield in Java
How to Stop Thread in Java with Code Example
How to sort ArrayList in Java with Example
Difference between JVM, JRE and JDK in Java
Read more:
http://javarevisited.blogspot.com/2012/01/difference-thread-vs-runnable-interface.html#ixzz3Ctqfnhpz