线程高级应用-心得9-空中网的三道面试题,考察应试者的线程掌握的深度
生活随笔
收集整理的這篇文章主要介紹了
线程高级应用-心得9-空中网的三道面试题,考察应试者的线程掌握的深度
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 空中網面試題1package com.kongzhongwang.interview;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;//myeclipse強大功能:將代碼直接復制到項目的src路徑下可以自動相應生成包名和類名
/*** * 空中網面試題1:現有程序代碼模擬產生16個日志對象,并且需要運行16秒才能打印完這些日志,請在程序中增加四個線程去調用* parseLog()方法來分頭打印這16個日志對象,程序只需運行4秒即可打印完這些日志對象。* 考察新技術BlockingQueue*/public class ReadLog {public static void main(String[] args) {/*此處有一個巧合:這里ArrayBlockingQueue<String>(1)和ArrayBlockingQueue<String>(16)* 達到的效果一樣,并且前者產生的數據組合更整齊;目前推測是巧合,希望大牛發現因果了告知一聲*/final BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);for (int i = 0; i < 4; i++) {new Thread(new Runnable() {public void run() {while (true) {try {String log = queue.take();parseLog(log);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}System.out.println("begin:" + (System.currentTimeMillis() / 1000));/** 模擬處理16個日志,下面代碼產生了16個日志對象;當前代碼需要運行16秒才能打印完成這些日志對象;* 修改程序代碼,開四個線程讓16個對象在4秒內打完*/for (int i = 0; i < 16; i++) { // 這行代碼不能改動final String log = "" + (i + 1); // 這行代碼不能改動{// ReadLog.parseLog(log);try {queue.put(log);} catch (InterruptedException e) {e.printStackTrace();}}}}// parseLog內部代碼不能動public static void parseLog(String log) {System.out.println(log + ":" + System.currentTimeMillis() / 1000);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}
}
2. 空中網面試題2package com.kongzhongwang.interview;import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;/*** 空中網面試題2: 現成程序中的Test類中的代碼在不斷地產生數據,然后交給TestDo.doSome()方法去處理;* 這就好像是生產者在不斷地產生數據,消費者在不斷地消費數據。請將程序改造成有10個線程來消費生產者產生的數據,* 這些消費者都調用TestDo.doSome()方法去處理,固每個消費者都需要1秒才能處理完,程序應該保證這些* 消費者線程依次有序的消費數據,只有上一個消費者消費完后,下一個消費者才能消費數據,下一個消費者是誰都可以, 但要保證消費者拿到的數據是有順序的。*/
public class Test {public static void main(String[] args) {//使用semaphore信號燈相當于上一個lock鎖final Semaphore semaphore = new Semaphore(1);//新的隊列方式final SynchronousQueue<String> queue = new SynchronousQueue<String>();for(int i=0;i<10;i++){new Thread(new Runnable() {@Overridepublic void run() {try {semaphore.acquire();String input = queue.take();String output = TestDo.doSome(input);System.out.println(Thread.currentThread().getName() + ":" + output);semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}}}).start();}System.out.println("begin:" + (System.currentTimeMillis() / 1000));for (int i = 0; i < 10; i++) { // 這行代碼不能改動String input = i + ""; // 這行代碼不能改動try {queue.put(input);} catch (InterruptedException e) {e.printStackTrace();}}}
}// TestDo類不能動
class TestDo {public static String doSome(String input) {try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}String output = input + ":" + (System.currentTimeMillis() / 1000);return output;}}3.空中網面試題3package com.kongzhongwang.interview;import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;public class Tests extends Thread {/*** 空中網面試題3: 現有程序同時啟動了四個線程去調用TestDo.doSome(key,value)方法;* 由于TestsDo.doSome(key,value)方法內的代碼是先暫停1秒,然后再輸出以秒為單位的當前時間值,* 所以會打印出四個相同的時間值,如下所示:4:4 1258199615 1:1 1258199615 3:3 1258199615 2:2* 1258199615 ;請修改代碼,如果有幾個線程調用TestDo.doSome(key,value)方法時;* 傳遞進去的key值相等(equals比較為true),則這幾個線程應互斥輸出結果,即當有兩個線程的key都為1時,* 它們中的一個要比其他線程晚一步輸出結果,如下所示:4:4 1258199615 1:1 1258199615 3:3 1258199615 1:2* 1258199616 ;總之每個線程中指定的key相等時;這些相等的線程應每隔1秒輸出時間值(要用互斥),* key不同,則并行執行(相互之間不互斥)*/private TestsDo testDo;private String key;private String value;private Tests(String key, String key2, String value) {this.testDo = TestsDo.getInstance();/** 常量“1”和“1”是同一個對象,下面這行代碼就是要用“1”+“”的方式產生新的對象;* 以實現內容沒有改變,仍然相等(都還為“1”),但對象卻不再是同一個的效果*/this.key = key + key2;/** a = "1"+"";* b = "2"+"";* a和b是同一個對象,因為編譯器在執行之前就會將其優化為 a=“1”;* 但是this.key = key + key2;這句,編譯器不會給你優化,* 因為你是屬性變量,編譯器不知道你將來要傳入什么值*/this.value = value;}public static void main(String[] args) {Tests a = new Tests("1", "", "1");Tests b = new Tests("1", "", "2");Tests c = new Tests("3", "", "3");Tests d = new Tests("4", "", "4");System.out.println("begin:" + (System.currentTimeMillis() / 1000));a.start();b.start();c.start();d.start();}public void run() {testDo.doSome(key, value);}
}class TestsDo {private TestsDo() {}private static TestsDo _instance = new TestsDo();public static TestsDo getInstance() {return _instance;}//傳統寫法,沒有考慮到線程并發問題
// private ArrayList keys = new ArrayList();private CopyOnWriteArrayList keys = new CopyOnWriteArrayList();public void doSome(Object key,String value){Object o = key;if(! keys.contains(o)){keys.add(o);}else{//迭代的過程中不能進行其他操作;for(Iterator iter = keys.iterator();iter.hasNext();){/*這里的休眠作用:為了讓大家看到,使用傳統的private ArrayList keys = new ArrayList();* 會導致Exception in thread "Thread-1" java.util.ConcurrentModificationException異常* 因為迭代的過程中不能進行其他操作;你非要在迭代的時候向其中添加數據就會導致這種異常,而且在迭代中放入休眠這種錯誤百發百中。*/try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();}Object oo = iter.next();if(o.equals(oo)){o = oo; }}}//這里為了區別是不同對象,所以不能直接使用synchronized(key)synchronized(o)//大括號內的是需要同步的代碼,不能改動{try{Thread.sleep(1000);System.out.println(key+":"+value+":" + (System.currentTimeMillis() / 1000));}catch(Exception e){e.printStackTrace();}}}
}
轉載于:https://www.cnblogs.com/yangkai-cn/archive/2013/02/12/4016963.html
總結
以上是生活随笔為你收集整理的线程高级应用-心得9-空中网的三道面试题,考察应试者的线程掌握的深度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP.ini修改配置下载上传文件大小
- 下一篇: tty_operations