- 方式一:同步代碼塊
synchroized(同步監視器的對象){
需要被同步的代碼
}
package threadtest; //使用同步代碼塊實現Runable接口的線程 public class Ruanble { public static void main(String[] args) { //創建實現類的對象 Num num=new Num(); //將此對象作為參數傳遞給Thread類的構造器,創建Thread類的對象 Thread thread1 =new Thread(num); Thread thread2 =new Thread(num); Thread thread3 =new Thread(num); //調用start()啟動創建的Thread對象 thread1.setName("線程一"); thread2.setName("線程二"); thread3.setName("線程三"); thread1.start(); thread2.start(); thread3.start(); } } //創建一個類實現Runable接口 class Num implements Runnable{ int ticket=100; //定義同步監視器,多個線程共同使用唯一的同步監視器 Object obj=new Object(); //重寫run方法 @Override public void run() { while (true) { synchronized (obj) { if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"開始售票,票號為"+ ticket); ticket--; }else { break; } } } } }
package threadtest; //同步代碼塊實現繼承Thread的線程 public class ThreadTest { public static void main(String[] args) { //創建子類對象 EvenThread e1=new EvenThread(); EvenThread e2=new EvenThread(); EvenThread e3=new EvenThread(); //調用線程的start()啟動 e1.setName("票口一"); e2.setName("票口二"); e3.setName("票口三"); e1.start(); e2.start(); e3.start(); } } //創建一個類繼承與Thread類 class EvenThread extends Thread{ static int ticket=100; //定義同步監視器,多個線程共同使用唯一的同步監視器 static Object obj=new Object(); //重寫run方法 @Override public void run() { while (true) { //synchronized (obj) {//方式一,確保同步監視器唯一 synchronized (EvenThread.class) {//EvenThread.class是唯一的 if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"開始售票,票號為"+ ticket); ticket--; }else { break; } } } } }
說明:共享數據------多個線程共同操作的數據
需要被同步的代碼塊,紀委操作共享的代碼
同步監視器,俗稱鎖,任何一個類都可以充當同步監視器,但是,要求多個線程共用一個監視器
- 方式二:同步方法:如果操作共享數據的代碼,完整的聲明在相依的方法中,着我們可以考慮將此方法作為同步方法來寫
- 非靜態的同步方法的默認監視器是this,不能修改
- 靜態的同步方法的監視器是當前類本身,不能修改
package threadtest; //創建同步方法實現Runable的線程 public class Ruanble { public static void main(String[] args) { //創建實現類的對象 Num num=new Num(); //將此對象作為參數傳遞給Thread類的構造器,創建Thread類的對象 Thread thread1 =new Thread(num); Thread thread2 =new Thread(num); Thread thread3 =new Thread(num); //調用start()啟動創建的Thread對象 thread1.setName("線程一"); thread2.setName("線程二"); thread3.setName("線程三"); thread1.start(); thread2.start(); thread3.start(); } } //創建一個類實現Runable接口 class Num implements Runnable{ int ticket=100; //定義同步監視器,多個線程共同使用唯一的同步監視器 Object obj=new Object(); //重寫run方法 @Override public void run() { while (true) { push(); } } //同步方法 public synchronized void push() {//這里有默認的同步監視器this,是唯一的 if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"開始售票,票號為"+ ticket); ticket--; } } }
//使用同步方法的來寫繼承Thread類的
package threadtest; public class ThreadTest { public static void main(String[] args) { //創建子類對象 EvenThread e1=new EvenThread(); EvenThread e2=new EvenThread(); EvenThread e3=new EvenThread(); //調用線程的start()啟動 e1.setName("票口一"); e2.setName("票口二"); e3.setName("票口三"); e1.start(); e2.start(); e3.start(); } } //創建一個類繼承與Thread類 class EvenThread extends Thread{ static int ticket=100; //定義同步監視器,多個線程共同使用唯一的同步監視器 static Object obj=new Object(); //重寫run方法 @Override public void run() { while (true) { push(); } } //public synchronized void push() {//此時不加static,會在new EvenThred對象是,導致同步監視器不是唯一的,故加上static,讓它先於類的創建而創建 public synchronized static void push(){ if (ticket>0) { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName() +"開始售票,票號為"+ ticket); ticket--; } } }
方式三使用lock鎖來確保安全,見下篇博客:鏈接---->
https://www.cnblogs.com/ylblikestudyJava/p/12378013.html