● 繼承Thread類別建立執行緒類,重寫run方法,run方法就是代表執行緒需要完成的任務,調用線程物件的start()來啟動該線程,線程類別已經繼承了Thread類,所以不能再繼承其他父類。
class ThreadTest extends Thread { Thread thread; public ThreadTest(Thread thread) { this.thread = thread; } @Override public void run() { synchronized (thread) { System.out.println("getObjectLock"); try { Thread.sleep(9000); } catch (InterruptedException ex) { ex.printStackTrace(); } System.out.println("ReleaseObjectLock"); } } }
● 實作Runnable介面建立執行緒類,定義Runnable實作類,重寫run方法
class RunnableImpl implements Runnable { public void run() { try { System.out.println("Begin sleep"); Thread.sleep(2000); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } } }
● 實作Callable接口,重寫call()方法,call()作為執行緒的執行體,具有返回值
● 線程池,使用線程池產生線程物件java.util.concurrent.ExecutorService、java.util.concurrent.Executors;
● 互斥同步:推薦使用synchronized 關鍵字進行同步, 在concurrent包中有ReentrantLock類, 實現效果差不多. 還是推薦原生態的synchronized.
● 非阻塞同步:需要硬體指令完成.常用的指令有: Test-and-Set Fetch-and-Increment Swap Compare-and-Swap (CAS) Load-Linked/Store-Conditional (LL/SC) 典型的應用在AtomicInteger 中
● 無同步方案:將變數保存在本地執行緒中,就不會出現多個執行緒並發的錯誤了。 java中主要使用的就是ThreadLocal這個類別。
thread.Join把指定的執行緒加入到目前執行緒,可以將兩個交替執行的執行緒合併為順序執行的執行緒。例如在執行緒B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。
t.join(); //使呼叫執行緒 t 在此之前執行完成。
t.join(1000); //等待t 線程,等待時間是1000毫秒,超時就不等了
public class JoinTest implements Runnable{ public static int a = 0; public void run() { for (int k = 0; k < 5; k++) { a = a + 1; } } public static void main(String[] args) throws Exception { Runnable r = new JoinTest(); Thread t = new Thread(r); t.start(); t.join();//等待t线程完成后输出,可保证a=5; System.out.println(a); } }
#Object的wait方法有三個重載方法,其中一個方法wait() 是無限期(一直)等待,直到其它執行緒呼叫notify或notifyAll方法喚醒目前的執行緒;另外兩個方法wait(long timeout) 和wait(long timeout, int nanos)允許傳入當前執行緒在被喚醒之前需要等待的時間,timeout為毫秒數,nanos為奈秒數。
notify方法只喚醒一個等待(物件的)執行緒並使該執行緒開始執行。所以如果有多個線程等待一個對象,這個方法只會喚醒其中一個線程,選擇哪個線程取決於作業系統對多線程管理的實作。
notifyAll 會喚醒所有等待(物件的)線程,儘管哪一個執行緒將會第一個處理取決於作業系統的實作。
這些方法可以使用於「生產者-消費者」問題,消費者是在隊列中等待物件的線程,生產者是在隊列中釋放物件並通知其他線程的線程。
● 繼承Thread類別建立執行緒類,重寫run方法,run方法就是代表執行緒需要完成的任務,呼叫執行緒物件的start()來啟動該線程,線程類別已經繼承了Thread類,所以不能再繼承其他父類。
class ThreadTest extends Thread { Thread thread; public ThreadTest(Thread thread) { this.thread = thread; } @Override public void run() { synchronized (thread) { System.out.println("getObjectLock"); try { Thread.sleep(9000); } catch (InterruptedException ex) { ex.printStackTrace(); } System.out.println("ReleaseObjectLock"); } } }
● 實作Runnable介面建立執行緒類,定義Runnable實作類,重寫run方法
class RunnableImpl implements Runnable { public void run() { try { System.out.println("Begin sleep"); Thread.sleep(2000); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } } }
● 實作Callable接口,重寫call()方法,call()作為執行緒的執行體,具有返回值
● 線程池,使用線程池產生線程物件java.util.concurrent.ExecutorService、java.util.concurrent.Executors;
● 互斥同步:推薦使用synchronized 關鍵字進行同步, 在concurrent包中有ReentrantLock類, 實現效果差不多. 還是推薦原生態的synchronized.
● 非阻塞同步:需要硬體指令完成.常用的指令有: Test-and-Set Fetch-and-Increment Swap Compare-and-Swap (CAS) Load-Linked/Store-Conditional (LL/SC) 典型的應用在AtomicInteger 中
● 無同步方案:將變數保存在本地執行緒中,就不會出現多個執行緒並發的錯誤了。 java中主要使用的就是ThreadLocal這個類別。
thread.Join把指定的執行緒加入到目前執行緒,可以將兩個交替執行的執行緒合併為順序執行的執行緒。例如在執行緒B中呼叫了執行緒A的Join()方法,直到執行緒A執行完畢後,才會繼續執行執行緒B。
t.join(); //使呼叫執行緒 t 在此之前執行完成。
t.join(1000); //等待t 線程,等待時間是1000毫秒,超時就不等了
public class JoinTest implements Runnable{ public static int a = 0; public void run() { for (int k = 0; k < 5; k++) { a = a + 1; } } public static void main(String[] args) throws Exception { Runnable r = new JoinTest(); Thread t = new Thread(r); t.start(); t.join();//等待t线程完成后输出,可保证a=5; System.out.println(a); } }
#Object的wait方法有三個重載方法,其中一個方法wait() 是無限期(一直)等待,直到其它執行緒呼叫notify或notifyAll方法喚醒目前的執行緒;另外兩個方法wait(long timeout) 和wait(long timeout, int nanos)允許傳入當前執行緒在被喚醒之前需要等待的時間,timeout為毫秒數,nanos為奈秒數。
notify方法只喚醒一個等待(物件的)執行緒並使該執行緒開始執行。所以如果有多個線程等待一個對象,這個方法只會喚醒其中一個線程,選擇哪個線程取決於作業系統對多線程管理的實作。
notifyAll 會喚醒所有等待(物件的)線程,儘管哪一個執行緒將會第一個處理取決於作業系統的實作。
這些方法可以使用於「生產者-消費者」問題,消費者是在隊列中等待物件的線程,生產者是在隊列中釋放物件並通知其他線程的線程。
以上是Java開發之多執行緒實作與執行緒安全的詳細內容。更多資訊請關注PHP中文網其他相關文章!