今天收到了同學的一個筆試題,內容如下:
4個線程 線程1 列印A 線程2列印B 線程3列印C 線程4列印D
向檔案1中寫入ABCDABCDABCD...
向檔案2寫入BCDABCDA...
向檔案3寫入CDABCDAB...
向檔案4寫入DABCDABC...
試著寫了一下:
package zmine.threadmore;import java.io.BufferedWriter;import java.io.FileOutputStream;import java.io.OutputStreamWriter;public class TestSleep {static int[] fileDeepth = {0,0,0,0}; //代表4個檔案的深度static String[] filepaths = {"d:\\txt1.txt","d:\\txt2.txt","d:\\txt3.txt","d:\\txt4.txt"};public static void main(String[] args){int count = 10; //列印次數new ThreadA(count).start();new ThreadB(count).start();new ThreadC(count).start();new ThreadD(count).start();}private static class ThreadA extends Thread{private int count ;public ThreadA(int count){this.count=count;}public void run(){int printAcount = 1;for(int i=0;i<count;i++){while(fileDeepth[printAcount-1] != i){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("begin A print ... " + System.currentTimeMillis());BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printAcount-1],true)));opt.write("A");System.out.println("第"+(i+1)+"次列印A,列印輸出在第"+printAcount+"個檔案");}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printAcount-1] = i+1; //深度加1printAcount--;if(printAcount == 0){printAcount =4 ;}}}}private static class ThreadB extends Thread{private int count ;public ThreadB(int count){this.count=count;}public void run(){int printBcount = 2;for(int i=0;i<count;i++){while(fileDeepth[printBcount-1] != i){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("begin B print ... " + System.currentTimeMillis());BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printBcount-1],true)));opt.write("B");System.out.println("第"+(i+1)+"次列印B,列印輸出在第"+printBcount+"個檔案");}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printBcount-1] = i+1;printBcount--;if(printBcount == 0){printBcount =4 ;}}}}private static class ThreadC extends Thread{private int count ;public ThreadC(int count){this.count=count;}public void run(){int printCcount = 3;for(int i=0;i<count;i++){while(fileDeepth[printCcount-1] != i){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("begin C print ... " + System.currentTimeMillis());BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printCcount-1],true)));opt.write("C");System.out.println("第"+(i+1)+"次列印C,列印輸出在第"+printCcount+"個檔案");}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printCcount-1] = i+1;printCcount--;if(printCcount == 0){printCcount =4 ;}}}}private static class ThreadD extends Thread{private int count ;public ThreadD(int count){this.count=count;}public void run(){int printDcount = 4;for(int i=0;i<count;i++){while(fileDeepth[printDcount-1] != i){try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("begin D print ... " + System.currentTimeMillis());BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printDcount-1],true)));opt.write("D");System.out.println("第"+(i+1)+"次列印D,列印輸出在第"+printDcount+"個檔案");}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printDcount-1] = i+1;printDcount--;if(printDcount == 0){printDcount =4 ;}}}}}
4個線程分別列印A,B,C,D, 每個線程在列印完成之後,會找到下次列印的檔案,這樣下次再列印的時候打在這個檔案中,
每次執行的時候會根據檔案的深度判斷,對於每個檔案來說,隊列的深度隨著線程列印的次數+1,下次再列印的時候判斷此時
隊列深度與列印次數的關係,如果隊列的深度與列印次數相同則說明這個時候列印的順序是正確的可以列印。
最近根據這個做了修改:
package zmine.threadmore;import java.io.BufferedWriter;import java.io.FileOutputStream;import java.io.OutputStreamWriter;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class TestWait {static int[] fileDeepth = {0,0,0,0}; //代表4個檔案的深度static String[] filepaths = {"d:\\txt1.txt","d:\\txt2.txt","d:\\txt3.txt","d:\\txt4.txt"};private static Lock lock = new ReentrantLock();private static Condition cond1 = lock.newCondition();private static Condition cond2 = lock.newCondition();private static Condition cond3 = lock.newCondition();private static Condition cond4 = lock.newCondition();public static void main(String[] args){int count = 10; //列印次數new ThreadA(count).start();new ThreadB(count).start();new ThreadC(count).start();new ThreadD(count).start();}private static class ThreadA extends Thread{private int count ;public ThreadA(int count){this.count=count;}public void run(){lock.lock();try{int printAcount = 1;for(int i=0;i<count;i++){while(fileDeepth[printAcount-1] != i){try {cond1.await();} catch (InterruptedException e) {e.printStackTrace();}}BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printAcount-1],true)));opt.write("A");System.out.println("第"+(i+1)+"次列印A,列印輸出在第"+printAcount+"個檔案 === " + System.currentTimeMillis());}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printAcount-1] = i+1; //深度加1printAcount--;if(printAcount == 0){printAcount =4 ;}cond2.signal();}}finally{lock.unlock();}}}private static class ThreadB extends Thread{private int count ;public ThreadB(int count){this.count=count;}public void run(){lock.lock();try{int printBcount = 2;for(int i=0;i<count;i++){while(fileDeepth[printBcount-1] != i){try {cond2.await();} catch (InterruptedException e) {e.printStackTrace();}}BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printBcount-1],true)));opt.write("B");System.out.println("第"+(i+1)+"次列印B,列印輸出在第"+printBcount+"個檔案 ==== " + System.currentTimeMillis());}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printBcount-1] = i+1;printBcount--;if(printBcount == 0){printBcount =4 ;}cond3.signal();}}finally{lock.unlock();}}}private static class ThreadC extends Thread{private int count ;public ThreadC(int count){this.count=count;}public void run(){lock.lock();try{int printCcount = 3;for(int i=0;i<count;i++){while(fileDeepth[printCcount-1] != i){try {cond3.await();} catch (InterruptedException e) {e.printStackTrace();}}BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printCcount-1],true)));opt.write("C");System.out.println("第"+(i+1)+"次列印C,列印輸出在第"+printCcount+"個檔案 == " + System.currentTimeMillis());}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printCcount-1] = i+1;printCcount--;if(printCcount == 0){printCcount =4 ;}cond4.signal();}}finally{lock.unlock();}}}private static class ThreadD extends Thread{private int count ;public ThreadD(int count){this.count=count;}public void run(){lock.lock();try{int printDcount = 4;for(int i=0;i<count;i++){while(fileDeepth[printDcount-1] != i){try {cond4.await();} catch (InterruptedException e) {e.printStackTrace();}}BufferedWriter opt = null ;try{opt = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepaths[printDcount-1],true)));opt.write("D");System.out.println("第"+(i+1)+"次列印D,列印輸出在第"+printDcount+"個檔案 === " + System.currentTimeMillis());}catch(Exception e){e.printStackTrace();}finally{if(opt != null){try{opt.close();}catch(Exception e){}}}fileDeepth[printDcount-1] = i+1;printDcount--;if(printDcount == 0){printDcount =4 ;}cond1.signal();}}finally{lock.unlock();}}}}