1、實現Runnable介面
同步代碼塊
使用synchronized關鍵字進行同步代碼塊的聲明,但是在使用此操作時必須明確的指出到底要鎖定的是哪個對象,一般是以當前對象為主.
synchronized(對象){ //一般都是講this鎖定
//鎖定對象
}
使用同步代碼塊解決:
package org.dennist.thread.demo;/** * * TicketThreadR.java * * @version : 1.1 * * @author : 蘇若年 <a href="mailto:DennisIT@163.com">發送郵件</a> * * @since : 1.0 建立時間: 2013-2-24 下午02:29:23 * * TODO : class TicketThreadR.java is used for ... * */public class TicketThreadR implements Runnable{ private int num = 5; //總共票數設定為5張 @Override public void run() { for(int i=0; i<10; i++){ //使用同步代碼塊 synchronized (this) { try { Thread.sleep(300); //休息300毫秒 } catch (InterruptedException e) { e.printStackTrace(); } if(this.num>0){ //列印買票資訊 System.out.println(Thread.currentThread().getName() + "買票: " + this.num--); } } } } public static void main(String[] args) { TicketThreadR ticketThread = new TicketThreadR(); new Thread(ticketThread,"售票口一").start(); //線程一 new Thread(ticketThread,"售票口二").start(); //線程二 new Thread(ticketThread,"售票口三").start(); //線程三 }}
同步方法
同步方法是在方法上增加synchronized關鍵字修飾
上面的問題使用同步代碼塊解決
package org.dennist.thread.demo;/** * * TicketThreadR.java * * @version : 1.1 * * @author : 蘇若年 <a href="mailto:DennisIT@163.com">發送郵件</a> * * @since : 1.0 建立時間: 2013-2-24 下午02:29:23 * * TODO : class TicketThreadR.java is used for ... * */public class TicketThreadR implements Runnable{ private int num = 5; //總共票數設定為5張 @Override public void run() { for(int i=0; i<10; i++){ sale(); //調用同步方法 } } //使用同步方法 public synchronized void sale(){ try { Thread.sleep(300); //休息300毫秒 } catch (InterruptedException e) { e.printStackTrace(); } if(this.num>0){ //列印買票資訊 System.out.println(Thread.currentThread().getName() + "買票: " + this.num--); } } public static void main(String[] args) { TicketThreadR ticketThread = new TicketThreadR(); new Thread(ticketThread,"售票口一").start(); //線程一 new Thread(ticketThread,"售票口二").start(); //線程一 new Thread(ticketThread,"售票口三").start(); //線程一 }}
2、繼承Thread類
錯誤分析:
class Thread2 extends Thread {int n = 100;public void run() {method();}public synchronized void method() {while (n > 0) {System.out.println(n--);}}}class Test {public static void main(String[] args) {Thread2 t1 = new Thread2();Thread2 t2 = new Thread2();Thread2 t3 = new Thread2();Thread2 t4 = new Thread2();t1.start();t2.start();t3.start();t4.start();}}
以下這段代碼無法達到同步的效果,雖然method方法使用了synchronized修飾,但每次都是通過new關鍵字出來的是不同的對象,他們的監視器對象不同,是吧。那麼如何讓這四個對象(t1、t2、t3、t4)使用同一個監視器來達到同步效果呢。
class SomeThread extends Thread { Object locker; public SomeThread(Object locker) { this.locker = locker; } public void run() { synchronized(locker) { //locker共同訪問的資源就可以了 //do something here } }}public class Test { public static void main(String[] args) { Object locker = new Object(); Thread[] t = new Thread[10]; for (int i=0; i<t.length; i++) { t[i] = new SomeThread(locker); //把共同資來源物件傳給線程 t[i].start(); } }}
只要鎖住共同訪問的資來源物件就可以了,如果想偷懶,直接synchronized(SomeThread.class),鎖住類對象,不過鎖類對象犧牲太大,效能有所下降,所以輕易不鎖類對象。