【发布时间】:2018-12-13 04:33:35
【问题描述】:
我为生产者消费者问题编写了一个多线程代码,其中我在消费者和生产者线程的 run 方法中编写了同步块,该线程锁定共享列表(我假设) 所以问题的关键是,列表上是否会有锁定,因为每个线程都有自己的同步块,但它们共享同一个列表实例
public class Main {
static boolean finishFlag=false;
final int queueSize = 20;
List<Integer> queue = new LinkedList<>();
Semaphore semaphoreForList = new Semaphore(queueSize);
public Main(int producerCount,int consumerCount) {
while(producerCount!=0) {
new MyProducer(queue,semaphoreForList,queueSize).start(); //produces the producer
producerCount--;
}
while(consumerCount!=0) {
new MyConsumer(queue,semaphoreForList,queueSize).start(); //produces the consumer
consumerCount--;
}
}
public static void main(String args[]) {
/*
* input is from command line 1st i/p is number of producer and 2nd i/p is number of consumer
*/
try {
Main newMain = new Main(Integer.parseInt(args[0]),Integer.parseInt(args[1]));
try {
Thread.sleep(30000);
}
catch(InterruptedException e) {
}
System.out.println("exit");
finishFlag=true;
}
catch(NumberFormatException e) {
System.out.println(e.getMessage());
}
}
}
class MyProducer extends Thread{
private List<Integer> queue;
Semaphore semaphoreForList;
int queueSize;
public MyProducer(List<Integer> queue, Semaphore semaphoreForList,int queueSize) {
this.queue = queue;
this.semaphoreForList = semaphoreForList;
this.queueSize = queueSize;
}
public void run() {
while(!Main.finishFlag) {
try {
Thread.sleep((int)(Math.random()*1000));
}
catch(InterruptedException e) {
}
try {
if(semaphoreForList.availablePermits()==0) {//check if any space is left on queue to put the int
System.out.println("no more spaces left");
}
else {
synchronized(queue) {
semaphoreForList.acquire(); //acquire resource by putting int on the queue
int rand=(int)(Math.random()*10+1);
queue.add(rand);
System.out.println(rand+" was put on queue and now length is "+(queueSize-semaphoreForList.availablePermits()));
}
}
}
catch(InterruptedException m) {
System.out.println(m);
}
}
}
}
public class MyConsumer extends Thread{
private List<Integer> queue; //shared queue by consumer and producer
Semaphore semaphoreForList;
int queueSize;
public MyConsumer(List<Integer> queue, Semaphore semaphoreForList,int queueSize) {
this.queue = queue;
this.semaphoreForList = semaphoreForList;
this.queueSize = queueSize;
}
public void run() {
while(!Main.finishFlag) {//runs until finish flag is set to false by main
try {
Thread.sleep((int)(Math.random()*1000));//sleeps for random amount of time
}
catch(InterruptedException e) {
}
if((20-semaphoreForList.availablePermits())==0) {//checking if any int can be pulled from queue
System.out.println("no int on queue");
}
else {
synchronized(queue) {
int input=queue.remove(0);//releases the resource(position in queue) by pulling the int out of the queue and computing factorial
semaphoreForList.release();
int copyOfInput=input;
int fact=1;
while(copyOfInput!=0) {
fact = fact*copyOfInput;
copyOfInput--;
}
System.out.println(input+" was pulled out from queue and the computed factorial is "+fact+
" the remaining length of queue is "+(queueSize-semaphoreForList.availablePermits()));
}
}
}
}
}
【问题讨论】:
-
我会考虑将其重写为大小的一小部分,具体取决于您想要保留多少,以制作一个更简单的示例来解决您要说明的问题。
-
简而言之,只要您同步的对象是共享的,它就可以工作。您可以删除信号量、睡眠和完成标志。您也不需要在持有锁时计算阶乘或打印结果。
标签: java multithreading concurrency producer-consumer