黑馬程序員_多線程

 ------- android培訓java培訓、期待與您交流! ----------

        我們使用計算機時,計算機上有很多的程序在執行,每個程序都被稱之爲一個進程,但是進程在執行的過程中,往往我們會看到一個程序同時做着多件不同的事情,其實並不是這樣子的,這就是利用了多線程,每個事情就是一個線程,程序在執行過程中不斷的來回切換正在執行線程,只不過CPU的執行速度太快以至於我們認爲程序在同時做着不同的事情。現在我們就來看看如何使用java開發多線程。

        java創建多線程有兩種方式。

        java中提供了一類一接口兩種方式創建多線程,類是Thread類,接口是Runnable接口

        方式一:通過查找API發現Thread類是一個抽象類,我們要創建抽象類的實例實際上需要的是抽象類的子類對象。

        對象的問題解決了以後,我們又該如何啓動線程,我們要用多線程做的事情又該怎麼寫呢?

        其實在Thread類中提供了兩個方法一個是run()方法,一個是start()方法,根據API中的介紹我們啓動線程調用的是start()方法,並且start()方法的底層其實也是調用run()方法。我們需要線程做得事情的代碼也是放在了run()方法中。

         首先創建Thread類的子類MyThread類

         其次重寫run()方法

         最後在main方法中創建子類對象並開啓線程

        

package cn.itheima01;

public class MyThread extends Thread{
	@Override
	public void run() {
		for(int x = 0; x < 100; x++){
			System.out.println(this.getName()+"--"+x);
		}
	
	}
}

package cn.itheima01;

public class MyThreadDemo {

	public static void main(String[] args) {

		MyThread mt1 = new MyThread();
		MyThread mt2 = new MyThread();
		
		mt1.start();
		mt2.start();
		
	}

}
        這樣一個簡單的多線程的例子就寫完了。

        方式二:通過接口去實現多線程,java提供了Runnable接口,只需要提供Runnable接口的子類對象同樣可以完成上述的操作,下面我們就來看看怎麼做的。

       

package cn.itheima02;

public class MyRunnable implements Runnable{

	@Override
	public void run() {

		for(int x = 0; x < 100; x++){
			System.out.println(Thread.currentThread().getName()+","+x);
		}
		
	}

}

package cn.itheima02;

public class MyThreadDemo {

	public static void main(String[] args) {

		MyRunnable mr1 = new MyRunnable();
		Thread th1 = new Thread(mr1);
		Thread th2 = new Thread(mr1);
		
		th1.start();
		th2.start();
			
	}

}
       以上兩種方法,就是使用java實現多線程的方法,其實以上兩種放發我們發現了還有很大的缺陷,就是數據不能共享。

       那麼java就提供了一個機制,同步機制。同步進制就是對線程加鎖,只有鎖對象是同一個時,程序纔會往下執行

       下面我們來看看java是怎麼利用鎖機制來同步的。

       java提供了關鍵字synchronized,

       需求:賣票,假設現在有100張票,有兩個窗口同時進行售票,用程序實現

       分析:兩個窗口同時進行售票的話,就代表了有兩個線程。數據是100

      

package cn.itheima10;

public class SellTicket implements Runnable {
	private int tickets = 100;
	private Object obj = new Object();

	@Override
	public void run() {

		while (true) {
			synchronized (obj) {
				if (tickets > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					System.out.println(Thread.currentThread().getName()
							+ "正在出售第" + (tickets--) + "張電影票");
				}
			}
		}

	}
}
       上面類中用到了一個sleep()方法,sleep()方法用於讓線程休眠,100所指的是100毫秒。
package cn.itheima10;

public class ThreadTicketDemo {

	public static void main(String[] args) {

		SellTicket st = new SellTicket();
		
		Thread t1 = new Thread(st,"售票窗口1");
		Thread t2 = new Thread(st,"售票窗口2");
		Thread t3 = new Thread(st,"售票窗口3");
		
		t1.start();
		t2.start();
		t3.start();
		
	}

}

其實上述方法使用的是同步代碼塊去實現,我們可以將同步代碼塊換成同步方法去實現,不過從上面的例子我們發現,用的是Object對象鎖,那麼同步方法的鎖又是什麼呢?

SellTicket類中的售票部分改成普通方法和靜態

package cn.itheima11;

public class SellTicket implements Runnable {
	private static int tickets = 100;
	private Object obj = new Object();
	private int x = 0;
	@Override
	public void run() {

		while (true) {
			if(x%2==0){
				synchronized (SellTicket.class) {
					if (tickets > 0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}

						System.out.println(Thread.currentThread().getName()
								+ "正在出售第" + (tickets--) + "張電影票");
					}
				}
			}else{
				sell();
			}
			x++;
		}

	}
	private synchronized void sell() {
		
			if (tickets > 0) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				System.out.println(Thread.currentThread().getName()
						+ "正在出售第" + (tickets--) + "張電影票");
			}
		
	}
}

package cn.itheima11;

public class SellTicket implements Runnable {
	private static int tickets = 100;
	private Object obj = new Object();
	private int x = 0;
	@Override
	public void run() {

		while (true) {
			if(x%2==0){
				synchronized (SellTicket.class) {
					if (tickets > 0) {
						try {
							Thread.sleep(100);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}

						System.out.println(Thread.currentThread().getName()
								+ "正在出售第" + (tickets--) + "張電影票");
					}
				}
			}else{
				sell();
			}
			x++;
		}

	}
	private static synchronized void sell() {
		
			if (tickets > 0) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				System.out.println(Thread.currentThread().getName()
						+ "正在出售第" + (tickets--) + "張電影票");
			}
		
	}
}
       改成以上方法實現,效果一樣,但是同步方法和靜態同步方法的的鎖對象是什麼呢?

        其實同步方法的鎖對象是this

       而靜態同步方法的鎖對象是當前類對象的字節碼文件


                 



        

             

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