樓主今天在面經上看到這個題,挺有意思,小小的題目對多線程的考量還挺多。大部分同窗都會使用 synchronized 來實現。樓主今天帶來另外兩種優化實現,讓你面試的時候,傲視羣雄!java
class ThreadPrintDemo2 { public static void main(String[] args) { final ThreadPrintDemo2 demo2 = new ThreadPrintDemo2(); Thread t1 = new Thread(demo2::print1); Thread t2 = new Thread(demo2::print2); t1.start(); t2.start(); } public synchronized void print2() { for (int i = 1; i <= 100; i += 2) { System.out.println(i); this.notify(); try { this.wait(); Thread.sleep(100);// 防止打印速度過快致使混亂 } catch (InterruptedException e) { // NO } } } public synchronized void print1() { for (int i = 0; i <= 100; i += 2) { System.out.println(i); this.notify(); try { this.wait(); Thread.sleep(100);// 防止打印速度過快致使混亂 } catch (InterruptedException e) { // NO } } } }
經過 synchronized 同步兩個方法,每次只能有一個線程進入,每打印一個數,就釋放鎖,另外一個線程進入,拿到鎖,打印,喚醒另外一個線程,而後掛起本身。循環反覆,實現了一個最基本的打印功能。面試
但,若是你這麼寫,面試官確定是不滿意的。樓主將介紹一種更好的實現。數組
public class ThreadPrintDemo { static AtomicInteger cxsNum = new AtomicInteger(0); static volatile boolean flag = false; public static void main(String[] args) { Thread t1 = new Thread(() -> { for (; 100 > cxsNum.get(); ) { if (!flag && (cxsNum.get() == 0 || cxsNum.incrementAndGet() % 2 == 0)) { try { Thread.sleep(100);// 防止打印速度過快致使混亂 } catch (InterruptedException e) { //NO } System.out.println(cxsNum.get()); flag = true; } } } ); Thread t2 = new Thread(() -> { for (; 100 > cxsNum.get(); ) { if (flag && (cxsNum.incrementAndGet() % 2 != 0)) { try { Thread.sleep(100);// 防止打印速度過快致使混亂 } catch (InterruptedException e) { //NO } System.out.println(cxsNum.get()); flag = false; } } } ); t1.start(); t2.start(); } }
咱們經過使用 CAS,避免線程的上下文切換,而後呢,使用一個 volatile 的 boolean 變量,保證不會出現可見性問題,記住,這個 flag 必定要是 volatile 的,若是不是,可能你的程序運行起來沒問題,但最終必定會出問題,並且面試官會立馬鄙視你。多線程
這樣就消除了使用 synchronized 致使的上下文切換帶來的損耗,性能更好。相信,若是你面試的時候,這麼寫,面試官確定很滿意。性能
但,咱們還有性能更好的。優化
class ThreadPrintDemo3{ static volatile int num = 0; static volatile boolean flag = false; public static void main(String[] args) { Thread t1 = new Thread(() -> { for (; 100 > num; ) { if (!flag && (num == 0 || ++num % 2 == 0)) { try { Thread.sleep(100);// 防止打印速度過快致使混亂 } catch (InterruptedException e) { //NO } System.out.println(num); flag = true; } } } ); Thread t2 = new Thread(() -> { for (; 100 > num; ) { if (flag && (++num % 2 != 0)) { try { Thread.sleep(100);// 防止打印速度過快致使混亂 } catch (InterruptedException e) { //NO } System.out.println(num); flag = false; } } } ); t1.start(); t2.start(); } }
咱們使用 volatile 變量代替 CAS 變量,減輕使用 CAS 的消耗,注意,這裏 ++num 不是原子的,但不妨礙,由於有 flag 變量控制。而 num 必須是 volatile 的,若是不是,會致使可見性問題。ui
到這裏,若是你面試的時候這麼寫,那麼,offer 就不遠啦!哈哈😆!!this
class ReverseDemo { public static void main(String[] args) { String test = "abcdefg"; System.out.println(new StringBuilder(test).reverse()); char[] arr = test.toCharArray(); for (int i = arr.length - 1; i >= 0; i--) { System.out.print(arr[i]); } } }
這個就比較簡單了,兩種方式,一個是 StringBuilder 的 reverse 方法,一個是轉換成數組本身打印。本身轉換性能更好,reverse 方法內部步驟更多。線程
好啦,但願你們面試成功!!code