1、两个线程交替打印0-100如何实现(口述)

来源:https://www.nowcoder.com/discuss/686890?type=post&order=create&pos=&page=1&ncTraceId=&channel=-1&source_id=search_post_nctrack&subType=2

使用CyclicBarrier

  1. package concurrent;
  2. import java.util.concurrent.BrokenBarrierException;
  3. import java.util.concurrent.CyclicBarrier;
  4. public class Solution {
  5. static CyclicBarrier barrier=new CyclicBarrier(2);
  6. static volatile int num=1;
  7. public static void main(String[] args) {
  8. Thread t1=new Thread(new printEven());
  9. Thread t2=new Thread(new printOdd());
  10. t1.start();
  11. t2.start();
  12. }
  13. public static class printOdd implements Runnable{
  14. @Override
  15. public void run() {
  16. for(int i=0;i<50;i++){
  17. while(num%2!=0);
  18. System.out.println(num);
  19. num++;
  20. try{
  21. barrier.await();
  22. }catch (BrokenBarrierException | InterruptedException e){
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. }
  28. public static class printEven implements Runnable{
  29. @Override
  30. public void run() {
  31. for(int i=0;i<50;i++){
  32. while(num%2==0);
  33. System.out.println(num);
  34. num++;
  35. try{
  36. barrier.await();
  37. }catch (BrokenBarrierException | InterruptedException e){
  38. e.printStackTrace();
  39. }
  40. }
  41. }
  42. }
  43. }

用ReentrantLock

  1. package concurrent;
  2. import java.util.concurrent.locks.Condition;
  3. import java.util.concurrent.locks.ReentrantLock;
  4. public class Print1To100 {
  5. static ReentrantLock lock = new ReentrantLock();
  6. static Condition condition = lock.newCondition();
  7. static volatile int num = 1;
  8. public static void main(String[] args) {
  9. Thread t1 = new Thread(new PrintOdd());
  10. Thread t2 = new Thread(new PrintEven());
  11. t1.start();
  12. t2.start();
  13. }
  14. public static class PrintOdd implements Runnable {
  15. @Override
  16. public void run() {
  17. for (int i = 0; i < 50; i++) {
  18. lock.lock();
  19. try {
  20. while (num % 2 == 0) {
  21. condition.await();
  22. }
  23. System.out.println(num);
  24. num++;
  25. condition.signal();
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. } finally {
  29. lock.unlock();
  30. }
  31. }
  32. }
  33. }
  34. public static class PrintEven implements Runnable {
  35. @Override
  36. public void run() {
  37. for (int i = 0; i < 50; i++) {
  38. lock.lock();
  39. try {
  40. while (num % 2 != 0) {
  41. condition.await();
  42. }
  43. System.out.println(num);
  44. num++;
  45. condition.signal();
  46. } catch (InterruptedException e) {
  47. e.printStackTrace();
  48. } finally {
  49. lock.unlock();
  50. }
  51. }
  52. }
  53. }
  54. }

△ 10次

2、手写生产者消费者模型

https://blog.csdn.net/weixin_43232955/article/details/108159971

使用ReentrantLock

Message类

  1. package concurrent;
  2. public class Message {
  3. private int id;
  4. private Object message;
  5. public Message(int id, Object message) {
  6. this.id = id;
  7. this.message = message;
  8. }
  9. public int getId() {
  10. return id;
  11. }
  12. public Object getMessage() {
  13. return message;
  14. }
  15. @Override
  16. public String toString() {
  17. return "Message{ " +
  18. "id=" + id +
  19. ", message=" + message +
  20. '}';
  21. }
  22. }

MessageQueue

  1. package concurrent;
  2. import java.util.LinkedList;
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.ReentrantLock;
  5. public class MessageQueue {
  6. private LinkedList<Message> queue = new LinkedList<>();
  7. private int capacity;
  8. public MessageQueue(int _capacity) {
  9. capacity = _capacity;
  10. }
  11. ReentrantLock lock = new ReentrantLock();
  12. Condition produce = lock.newCondition();
  13. Condition consume = lock.newCondition();
  14. public void put(Message m) {
  15. lock.lock();
  16. try {
  17. while (queue.size() == capacity) {
  18. System.out.println("队列已满,生产者等待...");
  19. produce.await();
  20. }
  21. queue.offerLast(m);
  22. System.out.println("生产消息" + m.toString());
  23. consume.signal();
  24. } catch (InterruptedException e) {
  25. e.printStackTrace();
  26. } finally {
  27. lock.unlock();
  28. }
  29. }
  30. public void get() {
  31. lock.lock();
  32. try {
  33. while (queue.isEmpty()) {
  34. System.out.println("队列为空,消费者等待...");
  35. consume.await();
  36. }
  37. Message m = queue.pollFirst();
  38. System.out.println("消费消息:" + m.toString());
  39. produce.signal();
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. } finally {
  43. lock.unlock();
  44. }
  45. }
  46. }

Client

  1. public class Client {
  2. public static void main(String[] args) {
  3. MessageQueue queue = new MessageQueue(2);
  4. Runnable produce = () -> {
  5. for (int i = 0; i < 10; i++) {
  6. Message m = new Message(i, "消息" + i);
  7. queue.put(m);
  8. }
  9. };
  10. Runnable consume = () -> {
  11. for (int i = 0; i < 10; i++) {
  12. queue.get();
  13. }
  14. };
  15. Thread t1 = new Thread(produce);
  16. Thread t2 = new Thread(consume);
  17. t1.start();
  18. t2.start();
  19. }
  20. }

使用BlockingQueue
△ 7次

3、设计一个无锁队列