Runnable介面實作多執行緒
package Day23; //多線稱實作方式2()----Runnable【介面】 public class RunnableDemo implements Runnable { //重寫此介面的run方法 @Override public void run() { for(int x=0;x<100;x++){ //public static Thread currentThread()回傳對當前正在執行的執行緒物件的參考---回傳當前執行的執行緒物件 //獲取當前執行緒物件的名稱---Thread.currentThread.getName System.out.println(Thread.currentThread().getName()); } } }
測驗類
package Day23; /* * /* * 方式2:實作Runnable介面 * 步驟: * A:自定義類MyRunnable實作Runnable介面 * B:重寫run()方法 * C:創建MyRunnable類的物件 * D:創建Thread類的物件,并把C步驟的物件作為構造引數傳遞 */ public class RunnableTest { public static void main(String[] args) { //創建RunnableTest物件 RunnableDemo rbt = new RunnableDemo(); //public Thread(Runnable target,String name)分配新的 Thread 物件, //target - 其 run 方法被呼叫的物件, //name - 新執行緒的名稱, Thread td = new Thread( rbt,"大海"); Thread td1= new Thread(rbt,"長江"); //使執行緒開始執行---虛擬機呼叫此方法 td.start(); td1.start(); } }
繼承類Thread--實作賣電影票
package cn.itcast_06; public class SellTicket extends Thread { // 定義100張票 // private int tickets = 100; // 為了讓多個執行緒物件共享這100張票,我們其實應該用靜態修飾 private static int tickets = 100; @Override public void run() { // 定義100張票 // 每個執行緒進來都會走這里,這樣的話,每個執行緒物件相當于買的是自己的那100張票,這不合理,所以應該定義到外面 // int tickets = 100; // 是為了模擬一直有票 while (true) { if (tickets > 0) { System.out.println(getName() + "正在出售第" + (tickets--) + "張票"); } } } }
package cn.itcast_06; /* * 某電影院目前正在上映賀歲大片(紅高粱,少林寺傳奇藏經閣),共有100張票,而它有3個售票視窗售票,請設計一個程式模擬該電影院售票, * 繼承Thread類來實作, */ public class SellTicketDemo { public static void main(String[] args) { // 創建三個執行緒物件 SellTicket st1 = new SellTicket(); SellTicket st2 = new SellTicket(); SellTicket st3 = new SellTicket(); // 給執行緒物件起名字 st1.setName("視窗1"); st2.setName("視窗2"); st3.setName("視窗3"); // 啟動執行緒 st1.start(); st2.start(); st3.start(); } }
利用Runnable介面實作電影票的售票
package Day23; //使用Runnable介面實作電影票的銷售----3個視窗 public class Movie implements Runnable { //定義100張電影票 private int ticket =100; //重寫Runnable介面的run方法 @Override public void run() { while(true){ if (ticket>0){ //Runnable介面不能直接呼叫getName方法需要通過獲取當前執行緒來獲取名稱 System.out.println(Thread.currentThread().getName()+"正在銷售第" +(ticket--)+"張電影票"); } } } }
package Day23; //實作Runnable介面的多執行緒 public class MovieDemo { public static void main(String[] args) { //創建資源物件 Movie m = new Movie(); //創建三個執行緒物件 //給出運行的物件---并給出執行緒名稱 Thread m1 = new Thread(m,"視窗1"); Thread m2 = new Thread(m,"視窗2"); Thread m3 = new Thread(m,"視窗3"); //啟動執行緒 m1.start(); m2.start(); m3.start(); } }
解決執行緒安全問題----解決賣電影票程式問題
* 同步代碼塊:
* synchronized(物件){
* 需要同步的代碼;
* }
package cn.itcast_09; public class SellTicket implements Runnable { // 定義100張票 private int tickets = 100; //創建鎖物件 private Object obj = new Object(); // @Override // public void run() { // while (true) { // synchronized(new Object()){ // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() + "正在出售第" // + (tickets--) + "張票"); // } // } // } // } @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--) + "張票"); } } } } }
測驗
package cn.itcast_09; /* * 如何解決執行緒安全問題呢? * * 要想解決問題,就要知道哪些原因會導致出問題:(而且這些原因也是以后我們判斷一個程式是否會有執行緒安全問題的標準) * A:是否是多執行緒環境 * B:是否有共享資料 * C:是否有多條陳述句操作共享資料 * * 我們來回想一下我們的程式有沒有上面的問題呢? * A:是否是多執行緒環境 是 * B:是否有共享資料 是 * C:是否有多條陳述句操作共享資料 是 * * 由此可見我們的程式出現問題是正常的,因為它滿足出問題的條件, * 接下來才是我們要想想如何解決問題呢? * A和B的問題我們改變不了,我們只能想辦法去把C改變一下, * 思想: * 把多條陳述句操作共享資料的代碼給包成一個整體,讓某個執行緒在執行的時候,別人不能來執行, * 問題是我們不知道怎么包啊?其實我也不知道,但是Java給我們提供了:同步機制, * * 同步代碼塊: * synchronized(物件){ * 需要同步的代碼; * } * * A:物件是什么呢? * 我們可以隨便創建一個物件試試, * B:需要同步的代碼是哪些呢? * 把多條陳述句操作共享資料的代碼的部分給包起來 * * 注意: * 同步可以解決安全問題的根本原因就在那個物件上,該物件如同鎖的功能, * 多個執行緒必須是同一把鎖, */ public class SellTicketDemo { 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(); } }
同步的特點:
* 前提:
* 多個執行緒
* 解決問題的時候要注意:
* 多個執行緒使用的是同一個鎖物件
* 同步的好處
* 同步的出現解決了多執行緒的安全問題,
* 同步的弊端
* 當執行緒相當多時,因為每個執行緒都會去判斷同步上的鎖,這是很耗費資源的,無形中會降低程式的運行效率,
同步代碼塊的鎖以及同步方法應用和鎖的問題
package cn.itcast_11; public class SellTicket implements Runnable { // 定義100張票 private static int tickets = 100; // 定義同一把鎖 private Object obj = new Object(); private Demo d = new Demo(); private int x = 0; //同步代碼塊用obj做鎖 // @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--) + "張票 "); // } // } // } // } //同步代碼塊用任意物件做鎖 // @Override // public void run() { // while (true) { // synchronized (d) { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "張票 "); // } // } // } // } @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 { // synchronized (d) { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "張票 "); // } // } sellTicket(); } x++; } } // private void sellTicket() { // synchronized (d) { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "張票 "); // } // } // } //如果一個方法一進去就看到了代碼被同步了,那么我就再想能不能把這個同步加在方法上呢? // private synchronized void sellTicket() { // if (tickets > 0) { // try { // Thread.sleep(100); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName() // + "正在出售第" + (tickets--) + "張票 "); // } // } private static synchronized void sellTicket() { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "張票 "); } } } class Demo { }
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* B:同步方法的格式及鎖物件問題?
* 把同步關鍵字加在方法上,
* 同步方法是誰呢?
* this----本類
package Day23; //使用Runnable介面實作電影票的銷售----3個視窗 /* * * 同步代碼塊: * synchronized(物件){ * 需要同步的代碼; * */ public class Movie implements Runnable { //定義100張電影票 private int ticket =100; //定義一個鎖物件 private Object obj = new Object(); private int x =0; //重寫Runnable介面的run方法 @Override public void run() { while(true) { if (x % 2 == 0) { synchronized (this) { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //Runnable介面不能直接呼叫getName方法需要通過獲取當前執行緒來獲取名稱 System.out.println(Thread.currentThread().getName() + "正在銷售第" + (ticket--) + "張電影票"); } } } else { sellTicket(); } x++; } } private synchronized void sellTicket() { if (ticket > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticket--) + "張票 "); } } }
測驗類
package Day23; //實作Runnable介面的多執行緒 public class MovieDemo { public static void main(String[] args) { //創建資源物件 Movie m = new Movie(); //創建三個執行緒物件 //給出運行的物件---并給出執行緒名稱 Thread m1 = new Thread(m,"視窗1"); Thread m2 = new Thread(m,"視窗2"); Thread m3 = new Thread(m,"視窗3"); //啟動執行緒 m1.start(); m2.start(); m3.start(); } }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*
* A:同步代碼塊的鎖物件是誰呢?
* 任意物件,
*
* B:同步方法的格式及鎖物件問題?
* 把同步關鍵字加在方法上,
*
* 同步方法是誰呢?
* this----本類
*
* C:靜態方法及鎖物件問題?
* 靜態方法的鎖物件是誰呢?
* 類的位元組碼檔案物件,(反射會講)
*/
package cn.itcast_11; /* * A:同步代碼塊的鎖物件是誰呢? * 任意物件, * * B:同步方法的格式及鎖物件問題? * 把同步關鍵字加在方法上, * * 同步方法是誰呢? * this * * C:靜態方法及鎖物件問題? * 靜態方法的鎖物件是誰呢? * 類的位元組碼檔案物件,(反射會講) */ public class SellTicketDemo { 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(); } }
以前執行緒安全類回顧
package cn.itcast_12; import java.util.ArrayList; import java.util.Collections; import java.util.Hashtable; import java.util.List; import java.util.Vector; public class ThreadDemo { public static void main(String[] args) { // 執行緒安全的類 StringBuffer sb = new StringBuffer(); Vector<String> v = new Vector<String>(); Hashtable<String, String> h = new Hashtable<String, String>(); // Vector是執行緒安全的時候才去考慮使用的,但是我還說過即使要安全,我也不用你 // 那么到呼叫誰呢? //Collections //public static <T> List<T> synchronizedList(List<T> list)回傳指定串列支持的同步(執行緒安全的)串列 List<String> list1 = new ArrayList<String>();// 執行緒不安全 List<String> list2 = Collections .synchronizedList(new ArrayList<String>()); // 執行緒安全 } }
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/456098.html
標籤:Java
上一篇:java的基礎語法
下一篇:java-GUI編程之AWT組件
