久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

詳解Java多線程與并發

瀏覽:115日期:2022-08-11 08:30:43
目錄一、進程與線程二、并發與并行1、線程安全問題2、共享內存不可見性問題三、創建線程1、繼承Thread類2、實現Runable接口3、實現Callable接口四、Thread類詳解1、線程特性2、Init方法3、構造方法4、線程狀態5、Start方法6、yield方法7、sleep方法8、join方法五、其他方法1、wait方法2、notify方法3、notifyAll()方法六、實例1、sleep2、join和中斷(推薦用標記中斷)3、優先級和守護進程4、生產者與消費者一、進程與線程

進程:是代碼在數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位。

線程:是進程的一個執行路徑,一個進程中至少有一個線程,進程中的多個線程共享進程的 資源。

雖然系統是把資源分給進程,但是CPU很特殊,是被分配到線程的,所以線程是CPU分配的基本單位。

詳解Java多線程與并發

二者關系:

一個進程中有多個線程,多個線程共享進程的堆和方法區資源,但是每個線程有自己的程序計數器和棧區域。

程序計數器:是一塊內存區域,用來記錄線程當前要執行的指令地址 。 棧:用于存儲該線程的局部變量,這些局部變量是該線程私有的,除此之外還用來存放線程的調用棧禎。 堆:是一個進程中最大的一塊內存,堆是被進程中的所有線程共享的。 方法區:則用來存放 NM 加載的類、常量及靜態變量等信息,也是線程共享的 。

二者區別:

進程:有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響。 線程:是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉。

1)簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.

2)線程的劃分尺度小于進程,使得多線程程序的并發性高。

3)另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。

4)每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

5)從邏輯角度來看,多線程的意義在于一個應用程序中,有多個執行部分可以同時執行。但操作系統并沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別

二、并發與并行

并發:是指同一個時間段內多個任務同時都在執行,并且都沒有執行結束。并發任務強調在一個時間段內同時執行,而一個時間段由多個單位時間累積而成,所以說并發的多個任務在單位時間內不一定同時在執行 。

并行:是說在單位時間內多個任務同時在執行 。

在多線程編程實踐中,線程的個數往往多于CPU的個數,所以一般都稱多線程并發編程而不是多線程并行編程。

并發過程中常見的問題:

1、線程安全問題

詳解Java多線程與并發

多個線程同時操作共享變量1時,會出現線程1更新共享變量1的值,但是其他線程獲取到的是共享變量沒有被更新之前的值。就會導致數據不準確問題。

2、共享內存不可見性問題

詳解Java多線程與并發

Java內存模型(處理共享變量)

Java 內存模型規定,將所有的變量都存放在主內存中,當線程使用變量時,會把主內存里面的變量復制到自己的工作空間或者叫作工作內存,線程讀寫變量時操作的是自己工作內存中的變量 。(如上圖所示)

詳解Java多線程與并發

(實際工作的java內存模型)

上圖中所示是一個雙核 CPU 系統架構,每個核有自己的控制器和運算器,其中控制器包含一組寄存器和操作控制器,運算器執行算術邏輔運算。CPU的每個核都有自己的一級緩存,在有些架構里面還有一個所有CPU都共享的二級緩存。 那么Java內存模型里面的工作內存,就對應這里的 Ll或者 L2 緩存或者 CPU 的寄存器

1、線程A首先獲取共享變量X的值,由于兩級Cache都沒有命中,所以加載主內存中X的值,假如為0。然后把X=0的值緩存到兩級緩存,線程A修改X的值為1,然后將其寫入兩級Cache,并且刷新到主內存。線程A操作完畢后,線程A所在的CPU的兩級Cache內和主內存里面的X的值都是l。

2、線程B獲取X的值,首先一級緩存沒有命中,然后看二級緩存,二級緩存命中了,所以返回X=1;到這里一切都是正常的,因為這時候主內存中也是X=l。然后線程B修改X的值為2,并將其存放到線程2所在的一級Cache和共享二級Cache中,最后更新主內存中X的值為2,到這里一切都是好的。

3、線程A這次又需要修改X的值,獲取時一級緩存命中,并且X=l這里問題就出現了,明明線程B已經把X的值修改為2,為何線程A獲取的還是l呢?這就是共享變量的內存不可見問題,也就是線程B寫入的值對線程A不可見。

synchronized 的內存語義:

這個內存語義就可以解決共享變量內存可見性問題。進入synchronized塊的內存語義是把在synchronized塊內使用到的變量從線程的工作內存中清除,這樣在synchronized塊內使用到該變量時就不會從線程的工作內存中獲取,而是直接從主內存中獲取。退出synchronized塊的內存語義是把在synchronized塊內對共享變量的修改刷新到主內存。會造成上下文切換的開銷,獨占鎖,降低并發性

Volatile的理解:

該關鍵字可以確保對一個變量的更新對其他線程馬上可見。當一個變量被聲明為volatile時,線程在寫入變量時不會把值緩存在寄存器或者其他地方,而是會把值刷新回主內存。當其他線程讀取該共享變量時-,會從主內存重新獲取最新值,而不是使用當前線程的工作內存中的值。volatile的內存語義和synchronized有相似之處,具體來說就是,當線程寫入了volatile變量值時就等價于線程退出synchronized同步塊(把寫入工作內存的變量值同步到主內存),讀取volatile變量值時就相當于進入同步塊(先清空本地內存變量值,再從主內存獲取最新值)。不能保證原子性

三、創建線程1、繼承Thread類

重寫run方法:使用繼承方式的好處是,在run()方法內獲取當前線程直接使用this就可以了,無須使用Thread.currentThread()方法;不好的地方是Java不支持多繼承,如果繼承了Thread類,那么就不能再繼承其他類。另外任務與代碼沒有分離,當多個線程執行一樣的任務時需要多份任務代碼。

public class ThreadRuning extends Thread{ public ThreadRuning(String name){ //重寫構造,可以對線程添加名字super(name); } @Override public void run() {while(true){ System.out.println('good time');//在run方法里,this代表當前線程 System.out.println(this);} } public static void main(String[] args){ThreadRuning threadRuning = new ThreadRuning('1111');threadRuning.start(); }}2、實現Runable接口

實現run方法:解決繼承Thread的缺點,沒有返回值

public class RunableTest implements Runnable { @Override public void run() {while (true) { System.out.println('good time');} } public static void main(String[] args) {RunableTest runableTest1 = new RunableTest();RunableTest runableTest2 = new RunableTest();new Thread(runableTest1).start();new Thread(runableTest1).start();new Thread(runableTest2).start(); }}3、實現Callable接口

實現call方法:

public class CallTest implements Callable { @Override public Object call() throws Exception {return 'hello world'; } public static void main(String[] args){FutureTask<String> futureTask = new FutureTask<String>(new CallTest());new Thread(futureTask).start();try { String result = futureTask.get(); System.out.println(result);} catch (InterruptedException e) { e.printStackTrace();} catch (ExecutionException e) { e.printStackTrace();} }}

使用繼承方式的好處是方便傳參,你可以在子類里面添加成員變量,通過set方法設置參數或者通過構造函數進行傳遞,而如果使用Runnable方式,則只能使用主線程里面被聲明為final的變量。不好的地方是Java不支持多繼承,如果繼承了Thread類,那么子類不能再繼承其他類,而Runable則沒有這個限制。前兩種方式都沒辦法拿到任務的返回結果,但是Callable方式可以

四、Thread類詳解1、線程特性

1、線程能被標記為守護線程,也可以是用戶線程

2、每個線程均分配一個name,默認為(Thread-自增數字)的組合

3、每個線程都有優先級.高優先級線程優先于低優先級線程執行. 1-10,默認為5

4、main所在的線程組為main,構造線程的時候沒有現實的指定線程組,線程組默認和父線程一樣

5、當線程中的run()方法代碼里面又創建了一個新的線程對象時,新創建的線程優先級和父線程優先級一樣.

6、當且僅當父線程為守護線程時,新創建的線程才會是守護線程.

7、當JVM啟動時,通常會有唯一的一個非守護線程(這一線程用于調用指定類的main()方法)

JVM會持續執行線程直到下面情況某一個發生為止:

1)類運行時exit()方法被調用 且 安全機制允許此exit()方法的調用.

2)所有非守護類型的線程均已經終止,or run()方法調用返回or在run()方法外部拋出了一些可傳播性的異常.

2、Init方法

/** * Initializes a Thread. * @param g 線程組 * @param target 執行對象 * @param name 線程名 * @param stackSize 新線程棧大小,為0表示忽略 * @param acc用于繼承的訪問控制上下文 * @param inheritThreadLocals如果值為true,從構造線程繼承可繼承線程局部變量的初始值*/private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { if (name == null) {throw new NullPointerException('name cannot be null'); } this.name = name; Thread parent = currentThread(); SecurityManager security = System.getSecurityManager(); //如果所屬線程組為nullif (g == null) {/* Determine if it’s an applet or not */ /* If there is a security manager, ask the security manager //如果有安全管理,查詢安全管理需要做的工作 what to do. */if (security != null) { g = security.getThreadGroup();} /* If the security doesn’t have a strong opinion of the matter use the parent thread group. *///如果安全管理在線程所屬父線程組的問題上沒有什么強制的要求if (g == null) { g = parent.getThreadGroup();} } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. *///無論所屬線程組是否顯示傳入,都要進行檢查訪問. g.checkAccess(); /* * Do we have the required permissions? */ if (security != null) {if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);} } g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon();//如果父線程為守護線程,則此線程也被 設置為守護線程. this.priority = parent.getPriority();//獲取父進程的優先級 if (security == null || isCCLOverridden(parent.getClass()))this.contextClassLoader = parent.getContextClassLoader(); elsethis.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext(); this.target = target; setPriority(priority); if (inheritThreadLocals && parent.inheritableThreadLocals != null)this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID 設置線程id*/ tid = nextThreadID();}3、構造方法

所有的構造方法都是調用init()方法

public Thread() { init(null, null, 'Thread-' + nextThreadNum(), 0);} public Thread(Runnable target) { init(null, target, 'Thread-' + nextThreadNum(), 0);} public Thread(Runnable target, AccessControlContext acc) { init(null, target, 'Thread-' + nextThreadNum(), 0, acc, false);} public Thread(ThreadGroup group, Runnable target) { init(group, target, 'Thread-' + nextThreadNum(), 0);} public Thread(String name) { init(null, null, name, 0);} public Thread(ThreadGroup group, String name) { init(group, null, name, 0);} public Thread(Runnable target, String name) { init(null, target, name, 0);} public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize);}4、線程狀態

public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;}

NEW:狀態是指線程剛創建, 尚未啟動

RUNNABLE:狀態是線程正在正常運行中, 當然可能會有某種耗時計算/IO等待的操作/CPU時間片切換等, 這個狀態下發生的等待一般是其他系統資源, 而不是鎖, Sleep等

BLOCKED:這個狀態下, 是在多個線程有同步操作的場景, 比如正在等待另一個線程的synchronized 塊的執行釋放, 或者可重入的 synchronized塊里別人調用wait() 方法, 也就是這里是線程在等待進入臨界區

WAITING:這個狀態下是指線程擁有了某個鎖之后, 調用了他的wait方法, 等待其他線程/鎖擁有者調用 notify / notifyAll 一遍該線程可以繼續下一步操作, 這里要區分 BLOCKED 和 WATING 的區別, 一個是在臨界點外面等待進入, 一個是在理解點里面wait等待別人notify, 線程調用了join方法 join了另外的線程的時候, 也會進入WAITING狀態, 等待被他join的線程執行結束

TIMED_WAITING:這個狀態就是有限的(時間限制)的WAITING, 一般出現在調用wait(long), join(long)等情況下, 另外一個線程sleep后, 也會進入TIMED_WAITING狀態

TERMINATED:這個狀態下表示 該線程的run方法已經執行完畢了, 基本上就等于死亡了(當時如果線程被持久持有, 可能不會被回收)

(在很多文章中都寫了running狀態,其實源碼里面只有六種的,當自己寫一個線程通過while一直保持執行狀態,然后使用jconsole工具去查看線程的狀態,確實是Runable狀態)

詳解Java多線程與并發

Api文檔是這么說的:

詳解Java多線程與并發

其實我們可以理解為兩種狀態,一個是running,表示正在執行,一個是runable,表示準備就緒了,只是在等待其他的系統資源。然后我們就可以理解如下圖

詳解Java多線程與并發

5、Start方法

public synchronized void start() { /*** 此方法并不會被主要方法線程or由虛擬機創建的系統組線程所調用.* 任何向此方法添加的新功能方法在未來都會被添加到虛擬機中.* 0狀態值代表了NEW的狀態.*/ if (threadStatus != 0) // 線程不能重復startthrow new IllegalThreadStateException(); /* Notify the group that this thread is about to be started* so that it can be added to the group’s list of threads* and the group’s unstarted count can be decremented. */ group.add(this); boolean started = false; try {start0(); //本地方法started = true; } finally {try { if (!started) {group.threadStartFailed(this); }} catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */} }}private native void start0();6、yield方法

public static native void yield();

是一個本地方法,提示線程調度器當前線程愿意放棄當前CPU的使用。如果當前資源不緊張,調度器可以忽略這個提示。本質上線程狀態一直是RUNNABLE,但是我可以理解為RUNNABLE到RUNNING的轉換

7、sleep方法

/** * 此方法會引起當前執行線程sleep(臨時停止執行)指定毫秒數. * 此方法的調用不會引起當前線程放棄任何監聽器(monitor)的所有權(ownership). */public static native void sleep(long millis) throws InterruptedException; public static void sleep(long millis, int nanos)throws InterruptedException { if (millis < 0) {throw new IllegalArgumentException('timeout value is negative'); } if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException( 'nanosecond timeout value out of range'); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) {millis++; } sleep(millis);}

sleep方法,有一個重載方法,sleep方法會釋放cpu的時間片,但是不會釋放鎖,調用sleep()之后從RUNNABLE狀態轉為TIMED_WAITING狀態

8、join方法

/** * 最多等待參數millis(ms)時長當前線程就會死亡.參數為0時則要持續等待. * 此方法在實現上:循環調用以this.isAlive()方法為條件的wait()方法. * 當線程終止時notifyAll()方法會被調用. * 建議應用程序不要在線程實例上使用wait,notify,notifyAll方法. */public final synchronized void join(long millis)throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; //如果等待時間<0,則拋出異常 if (millis < 0) {throw new IllegalArgumentException('timeout value is negative'); } //如果等待時間為0 if (millis == 0) {while (isAlive()) { wait(0);} } else {while (isAlive()) { long delay = millis - now; if (delay <= 0) {break; } wait(delay); now = System.currentTimeMillis() - base;} }}//等待時間單位為納秒,其它解釋都和上面方法一樣public final synchronized void join(long millis, int nanos)throws InterruptedException { if (millis < 0) {throw new IllegalArgumentException('timeout value is negative'); } if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException('nanosecond timeout value out of range'); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) {millis++; } join(millis);}//方法功能:等待一直到線程死亡.public final void join() throws InterruptedException { join(0);}

join某個線程A,會使得線程B進入等待,知道線程A結束,或者到達給定的時間,那么期間線程B處于BLOCKED的狀態,而不是線程A

五、其他方法

接下來聊一下Object類的wait,notify和notifyAll方法

1、wait方法

public final native void wait(long timeout) throws InterruptedException; //本地方法 參數為毫秒public final void wait(long timeout, int nanos) throws InterruptedException {//參數為毫秒和納秒 if (timeout < 0) {throw new IllegalArgumentException('timeout value is negative'); } if (nanos < 0 || nanos > 999999) {throw new IllegalArgumentException( 'nanosecond timeout value out of range'); } if (nanos > 0) {timeout++; } wait(timeout);}public final void wait() throws InterruptedException { wait(0);}

可見wait()和wait(long timeout, int nanos)都在在內部調用了wait(long timeout)方法。 下面主要是說說wait(long timeout)方法

wait方法會引起當前線程阻塞,直到另外一個線程在對應的對象上調用notify或者notifyAll()方法,或者達到了方法參數中指定的時間。

調用wait方法的當前線程一定要擁有對象的監視器鎖。

wait方法會把當前線程T放置在對應的object上的等待隊列中,在這個對象上的所有同步請求都不會得到響應。線程調度將不會調用線程T,在以下四件事發生之前,線程T會被喚醒(線程T是在其代碼中調用wait方法的那個線程)

1、當其他的線程在對應的對象上調用notify方法,而在此對象的對應的等待隊列中將會任意選擇一個線程進行喚醒。

2、其他的線程在此對象上調用了notifyAll方法

3、其他的線程調用了interrupt方法來中斷線程T

4、等待的時間已經超過了wait中指定的時間。如果參數timeout的值為0,不是指真實的等待時間是0,而是線程等待直到被另外一個線程喚醒為止。

被喚醒的線程T會被從對象的等待隊列中移除并且重新能夠被線程調度器調度。之后,線程T會像平常一樣跟其他的線程競爭獲取對象上的鎖;一旦線程T獲得了此對象上的鎖,那么在此對象上的所有同步請求都會恢復到之前的狀態,也就是恢復到wait被調用的情況下。然后線程T從wait方法的調用中返回。因此,當從wait方法返回時,對象的狀態以及線程T的狀態跟wait方法被調用的時候一樣。

線程在沒有被喚醒,中斷或者時間耗盡的情況下仍然能夠被喚醒,這叫做偽喚醒。雖然在實際中,這種情況很少發生,但是程序一定要測試這個能夠喚醒線程的條件,并且在條件不滿足時,線程繼續等待。換言之,wait操作總是出現在循環中,就像下面這樣:

synchronized(對象){ while(條件不滿足){ 對象.wait(); } 對應的邏輯處理}

如果當前的線程被其他的線程在當前線程等待之前或者正在等待時調用了interrupt()中斷了,那么會拋出InterruptedExcaption異常。直到這個對象上面的鎖狀態恢復到上面描述的狀態以前,這個異常是不會拋出的。

要注意的是,wait方法把當前線程放置到這個對象的等待隊列中,解鎖也僅僅是在這個對象上;當前線程在其他對象上面上的鎖在當前線程等待的過程中仍然持有其他對象的鎖。

這個方法應該僅僅被持有對象監視器的線程調用。 wait(long timeout, int nanos)方法的實現中只要nanos大于0,那么timeout時間就加上一毫秒,主要是更精確的控制時間,其他的跟wait(long timeout)一樣

2、notify方法

public final native void notify(); //本地方法

通知可能等待該對象的對象鎖的其他線程。由JVM(與優先級無關)隨機挑選一個處于wait狀態的線程。 在調用notify()之前,線程必須獲得該對象的對象級別鎖 執行完notify()方法后,不會馬上釋放鎖,要直到退出synchronized代碼塊,當前線程才會釋放鎖 notify()一次只隨機通知一個線程進行喚醒

3、notifyAll()方法

public final native void notifyAll();//本地方法

和notify()差不多,只不過是使所有正在等待池中等待同一共享資源的全部線程從等待狀態退出,進入可運行狀態 讓它們競爭對象的鎖,只有獲得鎖的線程才能進入就緒狀態

每個鎖對象有兩個隊列:就緒隊列和阻塞隊列

- 就緒隊列:存儲將要獲得鎖的線程

- 阻塞隊列:存儲被阻塞的線程

六、實例1、sleep

public class ThreadDemo1 { public static void main(String[] args) {MyThread mt = new MyThread(); //推薦MyRunnable mr = new MyRunnable();Thread t2 = new Thread(mr); mt.start();//啟動線程t2.start(); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + '-' + i); try {Thread.sleep(500); } catch (InterruptedException e) {e.printStackTrace(); }} }} /** * 實現線程的第一種方式:繼承thread類 */class MyThread extends Thread { @Override public void run() {for (int i = 0; i < 100; i++) { if (this.isInterrupted()) {break; } System.out.println(Thread.currentThread().getName() + '-' + i); try {Thread.sleep(500); } catch (InterruptedException e) {e.printStackTrace();this.interrupt(); } } }} /** * 實現線程的第二種方式:實現Runnable接口 */class MyRunnable implements Runnable { @Override public void run() {for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + '-' + i); try {Thread.sleep(500); } catch (InterruptedException e) {e.printStackTrace(); }} }}2、join和中斷(推薦用標記中斷)

public class ThreadDemo2 { public static void main(String[] args){ MyRunable2 mr2 = new MyRunable2();Thread t = new Thread(mr2);//t.start(); MyRunable3 mr3 = new MyRunable3();Thread t2 = new Thread(mr3);t2.start(); for (int i = 0; i < 50; i++) { System.out.println(Thread.currentThread().getName()+'--'+i); try {Thread.sleep(300); } catch (InterruptedException e) {e.printStackTrace(); } if(i==20){//try { //這些打開用來測試join// t.join();//讓t線程執行完畢//} catch (InterruptedException e) {// e.printStackTrace();//}//t.interrupt();//中斷線程,只是作了一個中斷標記,用于測試interrupt方法mr3.flag = false; //用于測試標記中斷 }} }} class MyRunable2 implements Runnable{ @Override public void run() {for (int i = 0; i < 50; i++) { if(Thread.interrupted()){//測試中斷狀態,此方法會把中斷狀態清除//....break; } System.out.println(Thread.currentThread().getName()+'--'+i); try {Thread.sleep(300); } catch (InterruptedException e) {e.printStackTrace();Thread.currentThread().interrupt(); }} }}<br>//標記中斷class MyRunable3 implements Runnable{ public boolean flag = true; public MyRunable3(){flag = true; } @Override public void run() {int i=0;while(flag){ System.out.println(Thread.currentThread().getName()+'==='+(i++)); try {Thread.sleep(300); } catch (InterruptedException e) {e.printStackTrace(); }} }}3、優先級和守護進程

public class ThreadDemo3 { public static void main(String[] args){MyRunnable4 mr4 = new MyRunnable4();Thread t = new Thread(mr4);t.setName('Thread-t');//優先級高可以提高該線程搶點CPU時間片的概率大t.setPriority(Thread.MAX_PRIORITY);//線程可以分成守護線程和 用戶線程,當進程中沒有用戶線程時,JVM會退出t.setDaemon(true);//把線程設置為守護線程System.out.println(t.isAlive());t.start();System.out.println(t.isAlive()); for (int i = 0; i < 50; i++) { System.out.println('main--'+i); try {Thread.sleep(200); } catch (InterruptedException e) {e.printStackTrace(); } if (i==5){Thread.yield();//讓出本次CPU執行時間片 }} }}class MyRunnable4 implements Runnable{ @Override public void run() {for (int i = 0; i < 50; i++) { System.out.println('--'+i); try {Thread.sleep(500); } catch (InterruptedException e) {e.printStackTrace(); }} }}4、生產者與消費者

定義一個接口:

package threadtest.procon; public interface AbstractStorage { void consume(int num); void product(int num);}

定義一個類實現接口,用于存放生產的東西

package threadtest.procon;import java.util.LinkedList;public class Storage implements AbstractStorage{ private final int MAX_SIZE = 100; private LinkedList list = new LinkedList(); @Override public void consume(int num) {synchronized (list){ while (list.size()<num){System.out.println('【要消費的產品數量】:' + num + 't【庫存量】:'+ list.size() + 't暫時不能執行消費任務!');try { list.wait(2000);} catch (InterruptedException e) { e.printStackTrace();} } for(int i=0;i<num;i++){list.remove(); } System.out.println('【已經消費產品數】:' + num + 't【現倉儲量為】:' + list.size()); list.notifyAll();} } @Override public void product(int num) {synchronized (list){ while(list.size()+num > MAX_SIZE){System.out.println('【要生產的產品數量】:' + num + 't【庫存量】:' + list.size() + 't暫時不能執行生成任務!');try { list.wait(2000);} catch (InterruptedException e) { e.printStackTrace();} } for(int i=0;i<num;i++){list.add(new Object()); } System.out.println('【已經生產產品數】:' + num + 't【現倉儲量為】:' + list.size()); list.notifyAll();} }}

生產者類:

package threadtest.procon;public class Producer extends Thread { private int num; public AbstractStorage abstractStorage; public Producer(AbstractStorage abstractStorage){this.abstractStorage = abstractStorage; } public void setNum(int num) {this.num = num; } public void produce(int num){abstractStorage.product(num); } @Override public void run() {produce(num); }}

消費者類:

package threadtest.procon;public class Consumer extends Thread { private int num; public AbstractStorage abstractStorage; public Consumer(AbstractStorage abstractStorage){this.abstractStorage = abstractStorage; } public void setNum(int num){this.num = num; } public void consume(int num){this.abstractStorage.consume(num); } @Override public void run() {consume(num); }}

測試類:

package threadtest.procon;public class Test { public static void main(String[] args){AbstractStorage abstractStorage = new Storage(); // 生產者對象Producer p1 = new Producer(abstractStorage);Producer p2 = new Producer(abstractStorage);Producer p3 = new Producer(abstractStorage);Producer p4 = new Producer(abstractStorage);Producer p5 = new Producer(abstractStorage);Producer p6 = new Producer(abstractStorage);Producer p7 = new Producer(abstractStorage); // 消費者對象Consumer c1 = new Consumer(abstractStorage);Consumer c2 = new Consumer(abstractStorage);Consumer c3 = new Consumer(abstractStorage); // 設置生產者產品生產數量p1.setNum(10);p2.setNum(20);p3.setNum(30);p4.setNum(40);p5.setNum(30);p6.setNum(20);p7.setNum(80); // 設置消費者產品消費數量c1.setNum(50);c2.setNum(70);c3.setNum(20); c1.start();c2.start();c3.start(); p1.start();p2.start();p3.start();p4.start();p5.start();p6.start();p7.start(); }}

詳解Java多線程與并發

以上就是詳解Java多線程與并發的詳細內容,更多關于Java 多線程 并發的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 91免费电影 | 亚洲国产精品一区二区三区 | 国产精品久久久久久久久久三级 | 91精品视频在线播放 | 欧洲另类在线1 | 免费国产wwwwwww网站 | 麻豆精品一区二区 | 中文字幕加勒比 | 精品久久国产老人久久综合 | 欧美日视频 | 色综合99| 精品无人乱码一区二区三区 | 欧美成人一区二区三区片免费 | 久久视频免费 | 精品久久一区二区 | 成人精品一区二区三区中文字幕 | 九色91视频| 欧美一级二级三级 | 成人网在线观看 | 伊人网站 | 欧洲精品视频在线观看 | 黄色手机在线观看 | 视频精品一区二区三区 | 精品中文字幕一区二区 | 亚洲在线视频 | 日韩毛片免费在线观看 | 日本一区二区不卡 | 一级免费黄视频 | 99re6在线| 久久久www成人免费精品 | 成人亚洲天堂 | 中文字幕日韩一区二区不卡 | 成人福利在线观看 | 欧美日韩中文国产一区发布 | 成年人在线看片 | 69性欧美高清影院 | 成人在线亚洲 | 黄a视频| 国产精品久久久久久中文字 | 午夜精品一区二区三区免费视频 | 一级毛片免费播放 | 亚洲国产精品久久久久久久 | 日韩在线视频观看 | 中文字幕在线免费播放 | 一本色道久久综合狠狠躁篇的优点 | 亚洲一区二区三区欧美 | 欧美成人免费在线视频 | 亚洲国产精品久久久久婷婷老年 | 国产精品无码专区在线观看 | 蜜桃av一区二区三区 | 看亚洲a级一级毛片 | 亚洲精品在 | 天天精品视频免费观看 | 神马电影午夜 | 欧美精品网站 | 综合色成人| av超碰| 中文字幕久久精品 | 91精品国产综合久久久久 | 亚洲国产精品一区二区久久,亚洲午夜 | 午夜精品一区二区三区在线视频 | av免费在线观看网站 | 日韩在线视频一区 | 免费观看羞羞视频网站 | 亚洲天堂中文字幕 | 男女中文字幕 | 国产精品久久精品 | 欧美 日韩 国产 一区 | 国产传媒一区 | 欧美日黄| 午夜视频 | 一级毛片免费视频 | 午夜免费影视 | 久久伊人一区二区 | 四虎影院入口 | 蜜桃视频网站在线观看 | 天堂精品 | 青青久久av北条麻妃海外网 | 欧美成人精品在线 | 国产偷录视频叫床高潮对白 | 亚洲高清视频在线观看 | 九九热在线免费视频 | 无码国模国产在线观看 | baoyu123成人免费看视频 | 国产日韩欧美在线 | 伊人超碰 | 欧美一区二区黄色片 | 久久精品成人免费视频 | 国产精品69毛片高清亚洲 | 中文字幕亚洲一区二区三区 | 午夜久久| 国产精品一区2区 | 免费毛片视频 | 亚洲九九精品 | 国产在线一区二区 | 成人网久久 | 操操操影院 | 伊人青青操 | 在线观看国产小视频 | 999在线观看精品免费不卡网站 | 国产精品网站在线看 | 狠狠爱天天操 | 国产三区在线成人av | 国产精品成人国产乱一区 | 亚洲成人二区 | 亚洲综合在线一区二区 | 亚洲午夜成激人情在线影院 | 久久精品 | 精品国产一区二区三区小蝌蚪 | 亚洲一区在线免费观看 | 国产午夜精品久久久久久久 | 在线观看理论电影 | 久久国产综合 | 成人精品网 | 欧美日韩一区二区三区在线观看 | 欧美日韩精品一区二区三区在线观看 | 亚洲a网 | 久久99深爱久久99精品 | 亚洲欧美一区二区精品中文字幕 | 亚洲一区中文字幕 | 91一区二区三区 | 午夜精品一区二区三区免费视频 | 一区二区三区在线播放 | 亚洲网站免费 | 国产伦精品一区二区三区四区视频 | 狠狠操夜夜操 | 一区二区不卡视频在线观看 | 欧美激情a∨在线视频播放 成人免费共享视频 | 91福利网址 | 在线观看午夜免费视频 | 91伊人 | 君岛美绪一区二区三区在线视频 | 三级黄色片在线 | 久久久久久久久99精品 | 一区二区三区四区免费观看 | 午夜剧院官方 | 亚洲五月婷婷 | 91综合网| 亚洲高清视频在线观看 | 99久久久成人国产精品 | 中文字幕国产一区 | 久久久精品 | 男女国产网站 | 国产精品一区二区三区免费 | 国产精品成人一区二区三区 | 国产精品久久久久久久久久久免费看 | 国产一区精品在线 | 日本一区二区精品 | 精品亚洲一区二区三区 | 一级黄色爱爱视频 | 二区在线观看 | 岛国伊人 | 九色在线观看 | 亚洲一区二区 | 欧美精品久久久 | 亚洲国产精品久久久 | 嫩草影院在线观看91麻豆 | 久久久久一区二区三区 | 久草视频在线播放 | 久久久www成人免费精品 | 日本在线不卡视频 | 国产超碰在线 | 欧美视频在线一区 | 国产一级片一区二区三区 | 日韩视频网 | 精品少妇一区二区三区在线播放 | japan国产精选videos | 精品久久99| 91av在| 国产精品久久久久9999鸭 | 亚洲国产精品久久久 | 欧美精品一区二区三区蜜桃视频 | 欧美成人精品一区二区男人看 | 国产精品丝袜视频 | 国产99久久久久久免费看农村 | 欧美日韩在线一 | 国产日产精品一区二区三区四区 | 男女做爰高清无遮挡免费视频 | 999视频在线 | 久久久国产视频 | 综合色爱| 欧美久久精品一级c片 | 国产成人精品免高潮在线观看 | 国产精品欧美一区二区三区 | 久久久99久久久国产自输拍 | 一级一片免费视频 | 亚洲成熟少妇视频在线观看 | 欧美精品一区二区三区在线四季 | 在线观看理论电影 | 特级a做爰全过程片 | 精品免费 | 视频一区 国产精品 | 美女诱惑av| 欧美色综合天天久久综合精品 | 91久久看片 | www.成人 | 狠狠亚洲| 黄桃av | 国产成人免费视频网站视频社区 | 亚洲欧美日韩国产 | 天堂男人在线 | 99re6在线视频精品免费 | 久久精品亚洲一区二区 | 在线观看国产www | 成年免费观看视频 | 久草青青| 久久综合一区二区 | 亚洲第一中文字幕 | 欧美三级在线 | 精品无码久久久久久国产 | 99精品欧美一区二区三区 | 久久99热精品免费观看牛牛 | 欧美精品日韩 | 国产高清一区二区 | 91视频在线网址 | 国产成人精品a视频一区www | 国产精品久久久久久吹潮 | 中文字幕在线影院 | 成人精品一区二区三区中文字幕 | 亚洲一区二区精品视频 | 欧美精品片 | 91麻豆精品国产91久久久更新资源速度超快 | 国产女精品 | 欧美另类国产 | 97av视频| 国产精品久久久久一区二区三区 | 国内自拍视频在线观看 | 天天干天天草 | 在线观看中文字幕亚洲 | 欧美中文字幕一区二区 | 欧美日韩国产精品久久久久 | 日穴视频在线观看 | 国产精品夜色一区二区三区 | 欧美日韩国产一区二区三区不卡 | 亚洲aⅴ天堂av在线电影软件 | 午夜精品久久久久久 | 蜜月久久99静品久久久久久 | 黄网站在线播放 | www.成人.com| 亚洲高清免费视频 | 亚洲精品资源在线观看 | 91tv亚洲精品香蕉国产一区 | 伦理午夜电影免费观看 | 一区二区三区在线免费看 | www.久久.com | 羞羞色影院| 中文字幕第56页 | 狠狠干天天干 | 免费不卡视频 | 国产伦精品一区二区三区四区视频 | 亚洲成熟少妇视频在线观看 | 躁躁躁日躁夜夜躁 | 免费视频二区 | 色婷婷久久久久swag精品 | 欧美黄色片免费观看 | 一区二区久久 | 一区二区三区四区在线播放 | 日韩精品一区二区三区中文在线 | 久久久久久久久99精品 | 国产在线精品一区二区三区 | 免费a视频 | 日韩视频精品 | 99精品视频在线观看 | 亚洲电影一区二区 | 国产91富婆养生按摩会所 | 亚洲一区在线日韩在线深爱 | 天天干一干 | 成人二区| 免费看一区二区三区 | 91精品国产综合久久久久久软件 | 成人在线免费 | 亚洲欧美日韩系列 | 亚洲成人日本 | 国产精品久久久久久久久久久久久久 | 色综合色综合 | 在线看国产 | 91视频免费播放 | 精品在线一区二区三区 | 伊人夜夜躁av伊人久久 | 日韩欧美在线免费观看 | 在线免费看黄视频 | 欧美日韩不卡 | 久久青| 99re在线免费 | 午夜国产在线 | 久久久久久国产精品久久 | 午夜小电影 | 91免费看| 日韩欧美一区二区三区久久婷婷 | 精品日韩欧美一区二区三区 | 天天碰天天操 | 九九热这里| 超级乱淫片国语对白免费视频 | 99亚洲| 中文av在线播放 | 欧美一区二区三区在线 | 亚洲高清电影 | 日韩视频在线免费观看 | 一级毛片视频 | 国产精品99久久 | 在线视频国产一区 | 亚洲第一天堂无码专区 | av官网在线| 中文久久| 欧美一区永久视频免费观看 | 五月婷婷激情 | 超碰操| 中文在线一区二区 | 亚洲精品乱码久久久久久蜜桃不卡 | 久久久久av| 在线播放亚洲 | 成人高清网站 | 久久精品一 | 亚洲精品一区二三区不卡 | 成人亚洲精品 | 中国妞xxxhd露脸偷拍视频 | 国产成人精品午夜 | 欧美激情在线精品一区二区三区 | 日本人做爰大片免费观看一老师 | 色爱区综合 | 天天干天天操 | 99精品视频在线 | 四季久久免费一区二区三区四区 | 午夜a级理论片915影院 | 一二区视频 | 国产精品毛片一区二区在线看 | 日本狠狠操 | 精品久久国产 | 成人午夜网| 久久色av | 欧美亚洲免费 | 中文字幕在线播放一区 | 国产精品亚洲视频 | 色综合88| 欧美激情在线精品一区二区三区 | 玖玖国产精品视频 | 国产高清不卡在线 | 男人的天堂久久 | 欧美不卡视频 | 在线看亚洲| 日韩精品一区二区三区在线播放 | 中文字幕在线观看av | 亚洲一区二区三区久久久 | 成人午夜av | av免费在线观看网站 | 亚洲毛片 | 亚洲国产精品精华液网站 | 久久久久成人精品 | 色综合欧美 | 一区二区三区日韩 | 曰批视频在线观看 | 91九色最新 | 国产日韩欧美一区二区 | 中文字幕 国产 | 免费午夜电影 | 日韩成人国产 | 中文字幕亚洲综合 | 久久精品| 国产一区二区在线免费观看 | 婷婷国产成人精品视频 | 国产激情毛片 | 日韩精品一二三 | 伊人久操| 精品免费久久 | 成人免费看片 | 五月网婷婷 | 久久久久久久99精品免费观看 | 亚洲免费视频一区 | 国产精品精品视频一区二区三区 | 久久久久久久久久久久久九 | 中文字幕一区在线观看视频 | 亚洲a网 | 久久精品不卡 | 精品久久久久久久 | 亚洲第一区国产精品 | 韩国成人精品a∨在线观看 国产伊人av | 天天干天天草 | 日韩精品一区二区三区在线观看 | 中文字幕日韩视频 | 97成人精品视频在线观看 | 欧美日韩中文在线观看 | 成年免费视频 | 一区二区三区观看视频 | 国产精品永久免费自在线观看 | 亚洲第一区在线 | 国产黄色大片免费看 | 日韩精品一区二区三区在线观看 | 色偷偷888欧美精品久久久 | 成人精品一区二区三区中文字幕 | 中文字幕在线观看av | 2018狠狠干| 午夜免费视频 | 亚洲精品综合 | 操到爽| 久久精品中文 | 欧美日韩国产在线播放 | 9se成人免费网站 | 欧洲免费视频 | 久久免费视频在线 | 亚洲午夜电影 | 欧美午夜精品久久久久免费视 | 亚洲综合国产 | 在线观看污片 | 日本欧美在线观看 | 97人人爱 | 久久99一区二区 | 国产欧美精品一区二区三区四区 | 久久青 | 成人不卡在线观看 | 欧美天天| 亚洲精品在线视频 | 国产一区二区在线看 | 国内精品三级 | 国产免费久久 | 热久久国产 | 国产精品69毛片高清亚洲 | 免费在线色 | 久久精品欧美一区二区三区不卡 | 国产精品久久久久一区二区三区 | 欧美黑人狂躁日本寡妇 | 最新中文字幕 | 久草在线| 99re在线精品 | 男女免费在线观看 | 精品中文在线 | 亚洲福利 | 中国一级毛片免费 | 精品在线一区二区 | 国产亚洲欧美一区二区三区 | 欧美日本免费 | 在线观看国产日韩欧美 | 啪一啪 | 亚洲 欧美日韩 国产 中文 | 婷婷成人在线 | 在线播放中文字幕 | 暖暖视频日韩欧美在线观看 | 国产亚洲欧美精品永久 | 国产v日产∨综合v精品视频 | 久久9999| 中文字幕国产在线视频 | 超碰免费观看 | 精品一区二区久久久久久久网站 | 日韩一区二区精品视频 | 奇米av | 亚洲永久免费 | 亚洲视频 欧美视频 | h免费在线观看 | 欧美成人在线影院 | 91精品久久久久久久久中文字幕 | 99精品一区二区三区 | 亚洲色图一区二区三区 | 亚洲av毛片一区二二区三三区 | 国产精品无码久久久久 | 岛国一区 | 日韩中文久久 | 久久久久国产精品一区二区三区 | 999在线观看精品免费不卡网站 | 天天摸天天看 | 日韩精品不卡 | www.天天操.com | 欧美日本国产一区 | 亚洲第一色片 | 国产精品一区二区三区四区 | 黄色在线免费看 | 欧美日韩一二三 | 97视频久久久 | 精品亚洲一区二区 | 99精品免费在线 | 超碰999 | 成人一级电影在线观看 | 99色影院 | 久久精品亚洲一区二区 | 国产拍拍拍拍拍拍拍拍拍拍拍拍拍 | 国产精品a久久久久 | 久久久久久久 | 成人一级片 | 日韩视频―中文字幕 | www.久久99 | 97夜夜操 | 手机在线观看av | 免费三级电影网站 | 一区二区三区精品视频免费看 | 99热在线播放 | 在线观看毛片网站 | 视频在线一区二区 | 亚洲精品午夜aaa久久久 | 亚洲激情在线 | 曰批视频在线观看 | 欧美黑人一级爽快片淫片高清 | 久久精品国产99国产精品 | 久久精品亚洲一区 | 欧美一区二区三区视频在线观看 | 婷婷激情五月 | 国产做a爰片久久毛片a我的朋友 | 亚洲一区二区精品视频 | 精品欧美一区二区精品久久久 | 性一级录像片片视频免费看 | 日日噜 | 成人网18免费网站 | 中文一区| 亚洲精品一区久久久久久 | 天天拍天天操 | 一级毛片免费完整视频 | 欧美日韩一区在线 | 操操操小说 | 无码日韩精品一区二区免费 | 亚洲一级毛片 | 黄色一级毛片免费 | 久在线视频 | 久久99精品久久久 | 久久久在线 | 日韩中文字幕av在线 | 国产精品日韩欧美一区二区三区 | 亚洲精品电影在线观看 | 精品国产乱码一区二区三区 | 欧美精品理论片大全 | 一区二区三区视频 | 4h影视| 黄色毛片一级 | 成人亚洲精品777777大片 | а天堂中文最新一区二区三区 | 国产精品99一区二区三区 | 日韩视频免费在线播放 | 欧美一级c片| 日本久久精品视频 | 亚洲精品a | 性开放xxxhd视频 | 中文字幕国产一区 | 精品久久久久久久久久久久久久久久久久 | 久久精品久久久 | 国产成人精品一区二区三区四区 | 天天操操| 国产精品一二三区视频 | 国产一级免费网站 | 欧美一区二区三区xxxx监狱 | 精品国产黄a∨片高清在线 99热婷婷 | 亚洲一二三区电影 | a级网站在线观看 | 久久国产精品视频 | 亚洲免费在线视频 | 日韩在线小视频 | 欧美日韩一区二区三区在线观看 | 免费视频爱爱太爽了 | 亚洲综合在线视频 | 国产精品一区二区三区免费视频 | 国产精品欧美久久久久一区二区 | 91精品久久久久 | 成人av电影网址 | 色婷婷综合久久久久中文一区二区 | 日韩午夜电影在线观看 | 亚洲国产精品久久久男人的天堂 | 天天插天天操 | 99精品电影 | 亚洲系列| 亚洲国产精品网站 | 久久精选视频 | 欧美一区二区三区免费 | 亚洲综合激情网 | 色鲁97精品国产亚洲 | 欧美一级在线免费观看 | 日本一区二区高清不卡 | 91麻豆精品国产91久久久资源速度 | 自拍偷拍小视频 | 国产午夜久久久久 | 国产剧情一区二区 | 午夜视频在线免费观看 | 一区免费看 | 国内精品久久久久久影视8 91一区二区在线观看 | 81精品国产乱码久久久久久 | 久久9999 | 久久久天堂国产精品女人 | 高清一区二区 | 国产精品久久久久久久久久免费看 | 在线视频二区 | 成人欧美一区二区三区黑人孕妇 | 少妇看av一二三区 | 久草新| 羞羞视频在线播放 | 超碰免费观看 | 欧美一区二 | 露娜同人18av黄漫网站 | 色吟av | 日韩精品 电影一区 亚洲 | 国产女人免费看a级丨片 | 国产婷婷久久 | 国产精品一区二区三区免费 | 日本免费黄色 | 精品视频久久 | 范冰冰一级做a爰片久久毛片 | 国产xxxx成人精品免费视频频 | 日本欧美在线观看 | 亚洲韩国精品 | 久久大陆| 国产视频一区二区在线观看 | 久久久精品免费观看 | 精品欧美乱码久久久久久 | 日韩视频一区 | 亚洲一二三 | 欧美日韩中文字幕 | 国产福利一区二区三区视频 | 精品国产欧美一区二区 | 亚洲lesbianxxxxhd 黄色av网站免费 | 99热播在线 | 黄色片免费观看网站 | 午夜午夜精品一区二区三区文 | 精品一区二区三区视频 | 国产精品一区二区不卡 | 狠狠操狠狠操 | 久久99久久98精品免观看软件 | 婷婷中文字幕 | 人人爱超碰| 影音先锋在线看片资源 | 日本一区二区三区四区 | 亚洲中出| a级片视频在线观看 |