简单的线程同步问题:两个线程交替执行N次【Synchronized、Lock、ArrayBlockingQueue】...
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                简单的线程同步问题:两个线程交替执行N次【Synchronized、Lock、ArrayBlockingQueue】...
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                
                            
                            
                            方法一:傳統的線程方法
import org.apache.log4j.Logger;/*** 兩個線程執行的代碼片段要實現同步互斥的效果,它們必須用同一個Lock對象。<br/>* 鎖是上在代表要操作的資源的類的內部方法中,而不是線程代碼中。<br/>* * 樣例:<br/>* 1)、主線程執行10次循環,接著子線程執行100此循環;<br/>* 2)、重復1)操作50次,結束。<br/>* * @author wangzhu* @date 2015-3-21下午8:00:57* */ public class ThreadCommunication {public static void main(String[] args) {final Bussiness bussiness = new Bussiness();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.main(i);}};}.start();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.sub(i);}};}.start();}}class Bussiness {private static final Logger logger = Logger.getLogger(Bussiness.class);/*** true:主線程<br/>* false:子線程<br/>* 默認執行主線程<br/>*/private boolean mark = false;public synchronized void main(int c) {while (mark) {// 表示當前是主線程,則進入等待狀態try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 當不是主線程,則開始執行for (int i = 0; i < 10; i++) {logger.info(c + "==main thread====" + i);}// 表示當前是主線程mark = true;// 喚醒所有的線程this.notifyAll();}public synchronized void sub(int c) {while (!mark) {// 表示當前是子線程,則進入等待狀態try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 當不是子線程,則開始執行for (int i = 0; i < 100; i++) {logger.info(c + "==sub thread====" + i);}// 表示當前是子線程mark = false;// 喚醒所有的線程this.notifyAll();}}
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;import org.apache.log4j.Logger;/*** 兩個線程執行的代碼片段要實現同步互斥的效果,它們必須用同一個Lock對象。<br/>* 鎖是上在代表要操作的資源的類的內部方法中,而不是線程代碼中。<br/>* * 樣例:<br/>* 1)、主線程執行10次循環,接著子線程執行100此循環;<br/>* 2)、重復1)操作50次,結束。<br/>* * @author wangzhu* @date 2015-3-22下午9:50:11* */ public class ConditionCommunication {private static final Logger logger = Logger.getLogger(ConditionCommunication.class);/*** @param args*/public static void main(String[] args) {final Bussiness bussiness = new Bussiness();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.sub(i);}};}.start();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.main(i);}};}.start();}static class Bussiness {private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();/*** true:主線程<br/>* false:子線程<br/>*/private boolean mark;public void main(int k) {// 加鎖 lock.lock();try {while (mark) {// 當前是主線程,則等待try {condition.await();} catch (InterruptedException e) {e.printStackTrace();}}for (int i = 0; i < 10; i++) {logger.info(k + "==main thread====" + i);}// 標記當前執行的是主線程mark = true;// 發出信號 condition.signal();} finally {// 釋放鎖 lock.unlock();}}public void sub(int k) {// 加鎖 lock.lock();try {while (!mark) {try {condition.await();} catch (InterruptedException e) {e.printStackTrace();}}for (int i = 0; i < 100; i++) {logger.info(k + "==sub thread====" + i);}// 標記當前執行的是子線程mark = false;// 發出信號 condition.signal();} finally {// 釋放鎖 lock.unlock();}}} }
class BoundedBuffer {final Lock lock = new ReentrantLock();//鎖對象final Condition notFull = lock.newCondition();//寫線程條件 final Condition notEmpty = lock.newCondition();//讀線程條件 final Object[] items = new Object[100];//緩存隊列int putptr/*寫索引*/, takeptr/*讀索引*/, count/*隊列中存在的數據個數*/;public void put(Object x) throws InterruptedException {lock.lock();try {while (count == items.length)//如果隊列滿了 notFull.await();//阻塞寫線程items[putptr] = x;//賦值 if (++putptr == items.length){putptr = 0;//如果寫索引寫到隊列的最后一個位置了,那么置為0 } ++count;//個數++notEmpty.signal();//喚醒讀線程} finally {lock.unlock();}}public Object take() throws InterruptedException {lock.lock();try {while (count == 0)//如果隊列為空notEmpty.await();//阻塞讀線程Object x = items[takeptr];//取值 if (++takeptr == items.length){takeptr = 0;//如果讀索引讀到隊列的最后一個位置了,那么置為0 }--count;//個數--notFull.signal();//喚醒寫線程return x;} finally {lock.unlock();}} }
import java.util.concurrent.ArrayBlockingQueue;import org.apache.log4j.Logger;/*** ArrayBlockingQueue(阻塞隊列)<br/>* put(anObject):<br/>* 把anObject加到BlockingQueue里,如果BlockQueue沒有空間,<br/>* 則調用此方法的線程被阻斷,直到BlockingQueue里面有空間再繼續.<br/>* * take():<br/>* 取走BlockingQueue里排在首位的對象,若BlockingQueue為空,<br/>* 阻斷進入等待狀態直到,BlockingQueue有新的數據被加入;<br/>* * @author wangzhu* @date 2015-3-23上午9:31:22* */ public class ArrayBlockingQueueCommunication {private static final Logger logger = Logger.getLogger(ArrayBlockingQueueCommunication.class);/*** @param args*/public static void main(String[] args) {final Bussiness bussiness = new Bussiness();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.sub(i);}};}.start();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.main(i);}};}.start();}static class Bussiness {// 阻塞隊列ArrayBlockingQueue<Integer> mainQuery = new ArrayBlockingQueue<Integer>(1);ArrayBlockingQueue<Integer> subQuery = new ArrayBlockingQueue<Integer>(1);{try {subQuery.put(1);} catch (InterruptedException e) {e.printStackTrace();}}public void main(int k) {try {mainQuery.put(1);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 10; i++) {logger.info(k + "==main thread====" + i);}try {subQuery.take();} catch (InterruptedException e) {e.printStackTrace();}}public void sub(int k) {try {subQuery.put(1);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 100; i++) {logger.info(k + "==sub thread====" + i);}try {mainQuery.take();} catch (InterruptedException e) {e.printStackTrace();}}} }
                        
                        
                        import org.apache.log4j.Logger;/*** 兩個線程執行的代碼片段要實現同步互斥的效果,它們必須用同一個Lock對象。<br/>* 鎖是上在代表要操作的資源的類的內部方法中,而不是線程代碼中。<br/>* * 樣例:<br/>* 1)、主線程執行10次循環,接著子線程執行100此循環;<br/>* 2)、重復1)操作50次,結束。<br/>* * @author wangzhu* @date 2015-3-21下午8:00:57* */ public class ThreadCommunication {public static void main(String[] args) {final Bussiness bussiness = new Bussiness();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.main(i);}};}.start();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.sub(i);}};}.start();}}class Bussiness {private static final Logger logger = Logger.getLogger(Bussiness.class);/*** true:主線程<br/>* false:子線程<br/>* 默認執行主線程<br/>*/private boolean mark = false;public synchronized void main(int c) {while (mark) {// 表示當前是主線程,則進入等待狀態try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 當不是主線程,則開始執行for (int i = 0; i < 10; i++) {logger.info(c + "==main thread====" + i);}// 表示當前是主線程mark = true;// 喚醒所有的線程this.notifyAll();}public synchronized void sub(int c) {while (!mark) {// 表示當前是子線程,則進入等待狀態try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}// 當不是子線程,則開始執行for (int i = 0; i < 100; i++) {logger.info(c + "==sub thread====" + i);}// 表示當前是子線程mark = false;// 喚醒所有的線程this.notifyAll();}}
?
?
2、JDK1.5之后(包括1.5)加入的并發包(Lock與Condition)import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;import org.apache.log4j.Logger;/*** 兩個線程執行的代碼片段要實現同步互斥的效果,它們必須用同一個Lock對象。<br/>* 鎖是上在代表要操作的資源的類的內部方法中,而不是線程代碼中。<br/>* * 樣例:<br/>* 1)、主線程執行10次循環,接著子線程執行100此循環;<br/>* 2)、重復1)操作50次,結束。<br/>* * @author wangzhu* @date 2015-3-22下午9:50:11* */ public class ConditionCommunication {private static final Logger logger = Logger.getLogger(ConditionCommunication.class);/*** @param args*/public static void main(String[] args) {final Bussiness bussiness = new Bussiness();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.sub(i);}};}.start();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.main(i);}};}.start();}static class Bussiness {private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();/*** true:主線程<br/>* false:子線程<br/>*/private boolean mark;public void main(int k) {// 加鎖 lock.lock();try {while (mark) {// 當前是主線程,則等待try {condition.await();} catch (InterruptedException e) {e.printStackTrace();}}for (int i = 0; i < 10; i++) {logger.info(k + "==main thread====" + i);}// 標記當前執行的是主線程mark = true;// 發出信號 condition.signal();} finally {// 釋放鎖 lock.unlock();}}public void sub(int k) {// 加鎖 lock.lock();try {while (!mark) {try {condition.await();} catch (InterruptedException e) {e.printStackTrace();}}for (int i = 0; i < 100; i++) {logger.info(k + "==sub thread====" + i);}// 標記當前執行的是子線程mark = false;// 發出信號 condition.signal();} finally {// 釋放鎖 lock.unlock();}}} }
?
?
JDK中的實例:class BoundedBuffer {final Lock lock = new ReentrantLock();//鎖對象final Condition notFull = lock.newCondition();//寫線程條件 final Condition notEmpty = lock.newCondition();//讀線程條件 final Object[] items = new Object[100];//緩存隊列int putptr/*寫索引*/, takeptr/*讀索引*/, count/*隊列中存在的數據個數*/;public void put(Object x) throws InterruptedException {lock.lock();try {while (count == items.length)//如果隊列滿了 notFull.await();//阻塞寫線程items[putptr] = x;//賦值 if (++putptr == items.length){putptr = 0;//如果寫索引寫到隊列的最后一個位置了,那么置為0 } ++count;//個數++notEmpty.signal();//喚醒讀線程} finally {lock.unlock();}}public Object take() throws InterruptedException {lock.lock();try {while (count == 0)//如果隊列為空notEmpty.await();//阻塞讀線程Object x = items[takeptr];//取值 if (++takeptr == items.length){takeptr = 0;//如果讀索引讀到隊列的最后一個位置了,那么置為0 }--count;//個數--notFull.signal();//喚醒寫線程return x;} finally {lock.unlock();}} }
?
參考:
http://blog.csdn.net/vking_wang/article/details/9952063
?
?
3、JDK1.5并發包中的阻塞隊列(ArrayBlockingQueue)import java.util.concurrent.ArrayBlockingQueue;import org.apache.log4j.Logger;/*** ArrayBlockingQueue(阻塞隊列)<br/>* put(anObject):<br/>* 把anObject加到BlockingQueue里,如果BlockQueue沒有空間,<br/>* 則調用此方法的線程被阻斷,直到BlockingQueue里面有空間再繼續.<br/>* * take():<br/>* 取走BlockingQueue里排在首位的對象,若BlockingQueue為空,<br/>* 阻斷進入等待狀態直到,BlockingQueue有新的數據被加入;<br/>* * @author wangzhu* @date 2015-3-23上午9:31:22* */ public class ArrayBlockingQueueCommunication {private static final Logger logger = Logger.getLogger(ArrayBlockingQueueCommunication.class);/*** @param args*/public static void main(String[] args) {final Bussiness bussiness = new Bussiness();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.sub(i);}};}.start();new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {bussiness.main(i);}};}.start();}static class Bussiness {// 阻塞隊列ArrayBlockingQueue<Integer> mainQuery = new ArrayBlockingQueue<Integer>(1);ArrayBlockingQueue<Integer> subQuery = new ArrayBlockingQueue<Integer>(1);{try {subQuery.put(1);} catch (InterruptedException e) {e.printStackTrace();}}public void main(int k) {try {mainQuery.put(1);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 10; i++) {logger.info(k + "==main thread====" + i);}try {subQuery.take();} catch (InterruptedException e) {e.printStackTrace();}}public void sub(int k) {try {subQuery.put(1);} catch (InterruptedException e) {e.printStackTrace();}for (int i = 0; i < 100; i++) {logger.info(k + "==sub thread====" + i);}try {mainQuery.take();} catch (InterruptedException e) {e.printStackTrace();}}} }
參考:
http://www.cnblogs.com/jackyuj/archive/2010/11/24/1886553.html
?
轉載于:https://www.cnblogs.com/xiaoxian1369/p/4356103.html
總結
以上是生活随笔為你收集整理的简单的线程同步问题:两个线程交替执行N次【Synchronized、Lock、ArrayBlockingQueue】...的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: C++链栈基本操作
- 下一篇: 《C++语言基础》实践参考——我的向量类
