java多线程解决同步问题的几种方式,原理和代码

2024-11-05 14:37:14
推荐回答(1个)
回答1:

在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。管道方法不建议使用。

  • wait()/notify()方法

  • await()/signal()方法

  • BlockingQueue阻塞队列方法

  • PipedInputStream/PipedOutputStream

  • 阻塞队列的一个简单实现:

  • public class BlockingQueue {

  •  private List queue = new LinkedList();

  •  private int  limit = 10;


  •  public BlockingQueue(int limit){

  •    this.limit = limit;

  •  }


  •  public synchronized void enqueue(Object item)throws InterruptedException  {

  •    while(this.queue.size() == this.limit) {

  •      wait();

  •    }

  •    if(this.queue.size() == 0) {

  •      notifyAll();

  •    }

  •    this.queue.add(item);

  •  }


  •  public synchronized Object dequeue()  throws InterruptedException{

  •    while(this.queue.size() == 0){

  •      wait();

  •    }

  •    if(this.queue.size() == this.limit){

  •      notifyAll();

  •    }


  •    return this.queue.remove(0);

  •  }}

  • 在enqueue和dequeue方法内部,只有队列的大小等于上限(limit)或者下限(0)时,才调用notifyAll方法。如果队列的大小既不等于上限,也不等于下限,任何线程调用enqueue或者dequeue方法时,都不会阻塞,都能够正常的往队列中添加或者移除元素。

  • wait()/notify()方法

  • 生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

    要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。