15 04 2021

0、面试题

实现:第一个线程从1到26,第二个线程从A到Z,然后要让这两个线程做到同时运行,交替输出,顺序打印。

输出结果:1A2B3C4D5E6F7G8H9I10J11K12L13M14N15O16P17Q18R19S20T21U22V23W24X25Y26Z

你有哪些玩法?

1、LockSupport

  1. public class LockSupportDemo {
  2. static Thread t1 = null, t2 = null;
  3. public static void main(String[] args) {
  4. String[] nums = new String[]{
  5. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  6. };
  7. String[] letters = new String[]{
  8. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  9. };
  10. t1 = new Thread(() -> {
  11. for (String num : nums) {
  12. System.out.print(num);
  13. LockSupport.unpark(t2);//唤醒 t2
  14. LockSupport.park();// t1 阻塞
  15. }
  16. }, "T1");
  17. t2 = new Thread(() -> {
  18. for (String letter : letters) {
  19. LockSupport.park();// t2 阻塞
  20. System.out.print(letter);
  21. LockSupport.unpark(t1);//唤醒 t1
  22. }
  23. }, "T2");
  24. t1.start();
  25. t2.start();
  26. }
  27. }

2、synchronized+wait+notify

  1. public class WaitNotifyDemo {
  2. static Thread t1 = null, t2 = null;
  3. public static void main(String[] args) {
  4. final Object o = new Object();
  5. String[] nums = new String[]{
  6. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  7. };
  8. String[] letters = new String[]{
  9. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  10. };
  11. t1 = new Thread(() -> {
  12. synchronized (o) {
  13. try {
  14. for (String num : nums) {
  15. System.out.print(num);
  16. o.notify();
  17. o.wait(); //阻塞 t1
  18. }
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. o.notify();//必须,否则无法停止程序
  23. }
  24. }, "T1");
  25. t2 = new Thread(() -> {
  26. synchronized (o) {
  27. try {
  28. for (String letter : letters) {
  29. System.out.print(letter);
  30. o.notify();
  31. o.wait(); //阻塞 t2
  32. }
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. o.notify(); //必须,否则无法停止程序
  37. }
  38. }, "T2");
  39. t1.start();
  40. t2.start();
  41. }
  42. }

3、ReentrantLock + 1个Condition

  1. public class LockConditionDemo {
  2. static Thread t1 = null, t2 = null;
  3. public static void main(String[] args) {
  4. String[] nums = new String[]{
  5. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  6. };
  7. String[] letters = new String[]{
  8. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  9. };
  10. ReentrantLock lock = new ReentrantLock();
  11. Condition condition = lock.newCondition();
  12. t1 = new Thread(() -> {
  13. lock.lock();
  14. try {
  15. for (String num : nums) {
  16. System.out.print(num);
  17. condition.signal();
  18. condition.await();
  19. }
  20. condition.signal();
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. } finally {
  24. lock.unlock();
  25. }
  26. }, "T1");
  27. t2 = new Thread(() -> {
  28. lock.lock();
  29. try {
  30. for (String letter : letters) {
  31. System.out.print(letter);
  32. condition.signal();
  33. condition.await();
  34. }
  35. condition.signal();
  36. } catch (Exception e) {
  37. e.printStackTrace();
  38. } finally {
  39. lock.unlock();
  40. }
  41. }, "T2");
  42. t1.start();
  43. t2.start();
  44. }
  45. }

4、ReentrantLock + 2个Condition

  1. public class LockConditionDemo2 {
  2. static Thread t1 = null, t2 = null;
  3. public static void main(String[] args) {
  4. String[] nums = new String[]{
  5. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  6. };
  7. String[] letters = new String[]{
  8. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  9. };
  10. ReentrantLock lock = new ReentrantLock();
  11. Condition conditionT1 = lock.newCondition();
  12. Condition conditionT2 = lock.newCondition();
  13. t1 = new Thread(() -> {
  14. lock.lock();
  15. try {
  16. for (String num : nums) {
  17. System.out.print(num);
  18. conditionT2.signal();
  19. conditionT1.await();
  20. }
  21. conditionT2.signal();
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. } finally {
  25. lock.unlock();
  26. }
  27. }, "T1");
  28. t2 = new Thread(() -> {
  29. lock.lock();
  30. try {
  31. for (String letter : letters) {
  32. System.out.print(letter);
  33. conditionT1.signal();
  34. conditionT2.await();
  35. }
  36. conditionT1.signal();
  37. } catch (Exception e) {
  38. e.printStackTrace();
  39. } finally {
  40. lock.unlock();
  41. }
  42. }, "T2");
  43. t1.start();
  44. t2.start();
  45. }
  46. }

5、自定义CAS实现

  1. public class CASDemo {
  2. enum ReadyToRun {T1, T2}
  3. static volatile ReadyToRun r = ReadyToRun.T1;
  4. static Thread t1 = null, t2 = null;
  5. public static void main(String[] args) {
  6. String[] nums = new String[]{
  7. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  8. };
  9. String[] letters = new String[]{
  10. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  11. };
  12. t1 = new Thread(() -> {
  13. for (String num : nums) {
  14. while (r != ReadyToRun.T1) {
  15. }
  16. System.out.print(num);
  17. r = ReadyToRun.T2;
  18. }
  19. }, "T1");
  20. t2 = new Thread(() -> {
  21. for (String letter : letters) {
  22. while (r != ReadyToRun.T2) {
  23. }
  24. System.out.print(letter);
  25. r = ReadyToRun.T1;
  26. }
  27. }, "T2");
  28. t1.start();
  29. t2.start();
  30. }
  31. }

6、Semaphore

  1. public class SemaphoreDemo {
  2. static Thread t1 = null, t2 = null;
  3. private static Semaphore semaphore1 = new Semaphore(1);
  4. private static Semaphore semaphore2 = new Semaphore(0);
  5. public static void main(String[] args) {
  6. String[] nums = new String[]{
  7. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  8. };
  9. String[] letters = new String[]{
  10. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  11. };
  12. t1 = new Thread(() -> {
  13. try {
  14. for (String num : nums) {
  15. semaphore1.acquire();
  16. System.out.print(num);
  17. semaphore2.release();
  18. }
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. }, "T1");
  23. t2 = new Thread(() -> {
  24. try {
  25. for (String letter : letters) {
  26. semaphore2.acquire();
  27. System.out.print(letter);
  28. semaphore1.release();
  29. }
  30. } catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }, "T2");
  34. t1.start();
  35. t2.start();
  36. }
  37. }

7、BlockingQueue

  1. public class BlockingQueueDemo {
  2. static BlockingQueue<String> queue1 = new ArrayBlockingQueue<>(1);
  3. static BlockingQueue<String> queue2 = new ArrayBlockingQueue<>(1);
  4. static Thread t1 = null, t2 = null;
  5. public static void main(String[] args) {
  6. String[] nums = new String[]{
  7. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  8. };
  9. String[] letters = new String[]{
  10. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  11. };
  12. t1 = new Thread(() -> {
  13. try {
  14. for (String num : nums) {
  15. System.out.print(num);
  16. queue1.put("ok");
  17. queue2.take();
  18. }
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. }, "T1");
  23. t2 = new Thread(() -> {
  24. try {
  25. for (String letter : letters) {
  26. queue1.take();
  27. System.out.print(letter);
  28. queue2.put("ok");
  29. }
  30. } catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }, "T2");
  34. t1.start();
  35. t2.start();
  36. }
  37. }

8、TransferQueue

  1. public class TransferQueueDemo {
  2. static Thread t1 = null, t2 = null;
  3. public static void main(String[] args) {
  4. String[] nums = new String[]{
  5. "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26"
  6. };
  7. String[] letters = new String[]{
  8. "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
  9. };
  10. TransferQueue<String> queue = new LinkedTransferQueue<>();
  11. t1 = new Thread(() -> {
  12. try {
  13. for (String num : nums) {
  14. queue.transfer(num);
  15. System.out.print(queue.take());
  16. }
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. }, "T1");
  21. t2 = new Thread(() -> {
  22. try {
  23. for (String letter : letters) {
  24. System.out.print(queue.take());
  25. queue.transfer(letter);
  26. }
  27. } catch (InterruptedException e) {
  28. e.printStackTrace();
  29. }
  30. }, "T2");
  31. t1.start();
  32. t2.start();
  33. }
  34. }
延伸阅读
  1. Java 代码块及代码块和构造方法的执行顺序
  2. java8新特性有哪些
  3. 抽象类(abstract class)和接口(interface)有什么异同
  4. 位运算符:与(&)、非(~)、或(|)、异或(^)
  5. 【面试题】实现打印26个数字和26个字母交替打印
发表评论