摘自:http://blog.csdn.net/mzwang123/article/details/7333885
線程狀態
1.程序通過Thread t = new Thread(),調用t.start()啓動一個線程,使該線程進入可運行(Runnable)的狀態。
2.由JVM的決定去調度(Scheduler) 在可運行狀態(Runnable)下的線程,使該線程處於運行 (Running) 狀態,由於JVM的調度會出現不可控性,即不是優先級高的先被調用,可能先調用,也可能後調用的的情況。運行狀態(Running)下,調用禮讓yield()方法,可以使線程回到可運行狀態(Runnable)下,再次JVM的調度(並不依賴優先級)。
3.線程在Running的過程中可能會遇到 ①睡眠(sleeping)、②等待(waiting)、③阻塞(Blocked)
①.調用join()和sleep()方法,sleep()時間結束或被打斷,join()中斷,IO完成都會回到Runnable狀態,等待JVM的調度。
②.調用wait(),使該線程處於等待池(wait blocked pool),直到notify()/notifyAll(),線程被喚醒被放到鎖池(lock blocked pool ),釋放同步鎖使線程回到可運行狀態(Runnable)
③.對Running狀態的線程加同步鎖(Synchronized)使其進入(lock blocked pool ),同步鎖被釋放進入可運行狀態(Runnable)。
4.線程run()運行結束或異常退出,線程到達死亡狀態(Dead)
sleep和wait的區別有:
1,類:這兩個方法來自不同的類分別是Thread和Object
2,鎖:最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其他線程可以使用同步控制塊或者方法。
3,域:wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,而sleep可以在任何地方使用
- synchronized(x){
- try {
- x.wait();或者x.notify()
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
4,停:其實兩者都可以讓線程暫停一段時間,但是本質的區別是一個線程的運行狀態控制,一個是線程之間的通訊的問題
.notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先級。
notifyAll():喚醒所有處入等待狀態的線程,注意並不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。
java中對Object的wait()和nofity(),在object中有一個wai()t隊列,一旦擁有該object的線程調用了該方法,線程狀態將從running 變爲 waiting 。只有在其他線程調用了該object的notify(),將隨機的從wait隊列中挑選一個線程(或者notify()待定全部線程),將其狀態從waitting 變爲 runningable。如果當前對象的wait隊列沒有線程,則不產生影響。
在兩個線程協同作用的場景中,至少要保用兩對wait() notify()函數,否則不能保證其順序性,比如消費者生產都模型。
- package com.wmz.helloworld;
- import java.util.Random;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- public class Demo extends android.app.Activity {
- private class Token {
- private String flag;
- public Token() {
- setFlag(null);
- }
- public void setFlag(String flag) {
- this.flag = flag;
- }
- public String getFlag() {
- return flag;
- }
- }
- private Token token = null;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.demo);
- Button btn = (Button) findViewById(R.id.button1);
- token = new Token();
- if(token.getFlag() ==null)
- Log.v("A","the token flag value is null");
- else
- Log.v("A","the token flag value is"+token.getFlag());
- btn.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- // TODO Auto-generated method stub
- WorkThread workthread = new WorkThread();
- workthread.start();
- Random r=new Random();
- for (int i = 0;i<10; i++) {
- try {
- Thread.sleep((r.nextInt(9)+1)*1000); //增加不確定性,至少睡眠1秒
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (token) {
- token.setFlag("wangmz"+Integer.toString(i));
- token.notifyAll();
- Log.v("Main",Integer.toString(i));
- }
- }
- }
- });
- }
- private class WorkThread extends Thread {
- @Override
- public void run() {
- Random r=new Random();
- while (true) {
- // try {
- // Thread.sleep((r.nextInt()+1)*1000);//可能在sleep的時候其他線程執行notify()。但此時對這個線程不起作用。所以結果不會按順序出現
- // } catch (InterruptedException e1) {
- // e1.printStackTrace();
- // }
- synchronized (token) {
- try {
- token.wait();
- Log.v("Main", "the value is " + token.getFlag());
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- Log.v("work","while!!");
- }
- }
- }
- }