java線程的基本應用

     要了解線程,先要了解進程。簡單的理解,進程就是一個正在執行的程序。而一個進程可能執行着多條線程,比如一個下載軟件正在下一個文件,它可能把文件分爲幾個部分,每一部分又分配一個線程負責下載。又比如,一臺電腦,同時運行着瀏覽器,QQ,播放器等等好多應用程序,也是通過一個個線程來完成的。
     那麼線程是否是同時運行的嗎?不是的,一個CPU,在同一個時間只能做一件事,只是它比較三心二意,一下子處理瀏覽器,一下子又去處理QQ,只是由於它的處理速度極快,使得所有應用程序的動作好像連貫一般。而且線程有個優先級,誰的優先級高一點,cpu就對誰好一點。該線程被執行到的概率就大一點,但並不表示優先級低的線程不會被執行到。
     說了這麼多,那麼如何實現應用程序的多線程呢?
     方法一、直接繼承Thread類,重寫run()。
 public class MyThread extends Thread { 
               public void run(){
                    ....    //要在線程裏運行的代碼  
               }
          }

     方法二、實現Runnable接口。
      public class MyThread implements Runnable {
               public void run(){
                    ...     //要在線程裏運行的代碼     
               }
          }
          

     其實這兩種方法的本質是一樣的,都是要實現Runnable接口,察看Thread類的源碼就可得知,Thread類本身就是實現了Runnable接口。最主要的一點是,無論用什麼方法,我們都是在它們的run()方法中執行我們的代碼。
     
     首先了解一下線程常用的方法
     start()   開始運行線程。
     run()   線程要執行的代碼。
     sleep(long millis)  讓線程睡眼millis毫秒時間,時間到後,線程重新進行就緒狀態(並非馬上開始)
     yield()  線程讓步,線程讓出cpu,重新進入就緒狀態
     wait()   讓線程暫停,誰來讓它重新開始呢?參考notify(),notifyAll();
     notify()   喚醒正在wait的線程,如果同時有多個線程在wait狀態,則任意喚醒一個。
     notifyAll()  喚醒正在wait的所有線程。
     join()  線程在掃行的過程中,讓其它線程加入執行後自己才執行。   

首先看一個例子:
public class ThreadTest extends Thread {

	public static void main(String[] args) {
		//主線程開始
		System.out.println("主線程開始。。。。。");
		//子線程開始
		new ThreadTest().start();
		
		//在主線程運行一此代碼
		Thread t = Thread.currentThread();
		for(int i=0; i<10; i++){
			System.out.println("我是"+t.getName()+",我的id是"+t.getId());
		}
	}
	
	@Override  //在子線程中執行的代碼
	public void run() {
		Thread t = Thread.currentThread();
		for(int i=0; i<10; i++){
			System.out.println("我是"+t.getName()+",我的id是"+t.getId());
		}
	}
}

運行的結果是不唯一的,多個線程執行,每時每刻線程都在搶着工作,搶一點工作一點,直到線程結束爲止。那麼線程什麼時候算是停止了呢?這要了解一下線程的生命週期
1、創建完一個線程對象後,線程並未開始,此時處於初始化新建狀態
2、當線程調用start()方法後,線程處於就緒狀態,但並沒有開始執行run()方法的內容。
3、當線程搶到cpu後,則就開始執行run()方法,處於運行狀態
4、當線程調用了sleep(),wait(),或者阻塞式的io方法,處於阻塞狀態
5、當線程執行完run()方法後,或者發生異常,應該說是未捕獲的異常,則線程處於死亡狀態

下面是一個讓方塊在窗口內移動的例子,大家看一下多線程的使用。
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MovingRect extends JPanel implements Runnable {
	private int x = 10;
	private int y = 10;

	public static void main(String[] args) {
		//設置窗口屬性。
		JFrame frame = new JFrame();
		frame.setSize(800, 600);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocation(250, 50);
		frame.add(new MovingRect());
		frame.setVisible(true);
	}

	public MovingRect() {
		//設置面板屬性
		this.setSize(800, 600);
		this.setLocation(10, 10);
		
		//創建子線程,並讓它進入就緒狀態。
		Thread t = new Thread(this);
		t.start();
		
		this.setVisible(true);
	}
	
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		Color c = g.getColor();
		g.setColor(Color.RED);
		//畫一個方塊
		g.fillRect(x, y, 15, 15);
		g.setColor(c);
	}
	
	//子線程要做的就是更改方塊的位置座標,並刷新。
	public void run() {
		while (true) {
			this.x += 8;
			this.y += 6;
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			this.repaint();
		}
	}
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章