I am trying to familiarize myself with the ReentrantLock and ConditionVariable classes. I implemented this Scala code ( without anything "Scala specific" in it ):
object Conditioned {
var pops = 0
var max = 20
abstract class NamedThread extends Thread {
def myName = this.toString
}
class Producer(lock:Lock,condition:Condition,source:ListBuffer[Int]) extends NamedThread {
override def run = {
var number = max
var current = 0
while(current < number)
{
if(lock.tryLock)
{
try
{
current += 1
source += current
println("producer added data:"+current)
condition.signal
} finally {
lock.unlock
Thread.sleep(100)
}
}
}
}
}
class Consumer(lock:Lock,condition:Condition,source:ListBuffer[Int]) extends NamedThread {
override def run = {
while(pops < max) {
println("awaiting")
while(source.isEmpty)
condition.await
println("consumer try lock")
if(lock.tryLock)
{
try {
val data = source(source.size - 1)
source -= data
println("consumer received data:"+data+" hello from:"+myName)
pops += 1
} finally { lock.unlock }
}
}
}
}
def main(args:Array[String]) = {
val lock = new ReentrantLock
val condition = lock.newCondition
var lb = new collection.mutable.ListBuffer[Int]()
val producer = new Producer(lock,condition,lb)
val consumer = new Consumer(lock,condition,lb)
val cons2 = new Consumer(lock,condition,lb)
val threads = Array(producer,consumer,cons2)
threads.foreach(_.start)
threads.foreach(_.join)
}
}
I am trying to produce 20 elements in a ListBuffer, and then read them. I am missing something, because my output tends to look like this:
awaiting
consumer try lock
producer added data:1
awaiting
consumer try lock
consumer received data:1 hello from:Thread[Thread-51,5,trap.exit]
awaiting
awaiting
producer added data:2
producer added data:3
producer added data:4
producer added data:5
producer added data:6
producer added data:7
producer added data:8
producer added data:9
producer added data:10
producer added data:11
producer added data:12
producer added data:13
producer added data:14
producer added data:15
producer added data:16
producer added data:17
producer added data:18
producer added data:19
producer added data:20
But I don't know what. I am using a ConditionVariable so that I can signal the Consumer when data has been added, but it seems it only works the first time , and after that the producer runs until it finishes. What do I need to change to make it run in a consumer-producer fashion, and not in a robot worker kind of way? :)
Your consumer must await
while holding the lock (as the javadocs for the method state).
also, you shouldn't be using tryLock
, you should just be using lock
. you only use tryLock
if you are going to do something else if lock acquisition fails. in your case, if lock acquisition fails, you just try to acquire it again.