[Java] Thread synchronization.



  • Hi,

    I have to write a little program which in fact resembles the "producer and consumer" problem.
    But there's a little extra to it, the producer has to check for a timeout.

    I have writte a little incomplete example to show you what i mean:


    
    
    public class Observer implements Runnable {
           
        private final static long CYCLE_TIME = 10000;
        private final static long MAX_TIME = 180000;
        private final static long TIMEOUT = MAX_TIME + CYCLE_TIME;
       
        private final Container container; //Some self-defined container
       
        private Something SOMETHING = new Something("foo"); //whatever ;)
       
        private Thread workerThread;
       
       
        public Observer() throws {
           
            container = new Container();
           
            worker = new Worker(container);
            workerThread = new Thread(worker);
           
        }
       
        public void run() {
            while(!Thread.currentThread().isInterrupted()) {
               
                workerThread.start();
               
                synchronized (container) {
                    container.add(SOMETHING);
                    container.notify();
                    container.wait(TIMEOUT); //There's a little Problem now see * in posting
                   
                    if(/*something like timeout hit == true*/) {
                        //timeout detected
                        //do stuff   
                    } else {
                        //all working properly   
                    }
                }   
            }
        }
    }

    public class Worker implements Runnable {
       
        private final Container container;
        private Something something;
       
        public Worker(Container container) {
            this.container = container;
        }
       
        public void run() {
            while(!Thread.currentThread().isInterrupted()) {
               
                synchronized (container) {
                    container.wait();
                    if(!container.isEmpty()) {
                        something = container.get();
                    } else {
                        continue;
                    }
                    //do something with something ;)
    container.remove();
                    container.notify();
                }
            }
        }
    }


    So you see that i synchronize over the container that both threads have in common.
    I think i managed to get mutual exclusion in there, if not please help me make this better.

    *But the real Problem is, how to find out that TIMEOUT was hit. I mean i could get a timestamp before add TIMEOUT and check if its in close boundaries, and if container is empty.
    But thats a bit fuzzy and in don't tink thats a good way to do this.

    To get to the point:
    What i want to achieve is a producer, it only produces one item, no queu, and lets the consumer work on it. But the consumer mustn't take longer than TIMEOUT to achieve his job.
    I have to detect this. Also there must be mutual exclusion over the container.

    I see a few problems of which im not sure they even are problems :)
    Rather i feel uncomfortable with this stuff since i am not very experienced in parallel programming. So if you got help, hints, tips or anything else...

     
    Thanks in advance,
    nFec

     

     



    1. Why are you using a custom container instead of a BlockingQueue (linked or array) from java.util.concurrent?
    2. In fact, since your application/problem seems to need only 1 item in the queue/container, I think you could use a pair of SynchronousQueues as a kind of message-passing system (or LinkedBlockingQueues if the producer can send more than one item to the consumer):

    1 SynchroneousQueue from the producer to the consumer, upon starting the consumer does a take() on the queue (will wait until the producer puts something on it), the consumer is the starting point of the second SQ.

    The producer then puts your item on SQ1 (which the consumer will automatically retrieve and remove from the queue), then does a poll() on the SQ2 with the timeout you want.

    Upon completion of its work, the consumer will put() something on SQ2 (anything that's not null)

    Then it's very simple: if the producer's SQ2.poll() returns an object then the consumer ended its work before the timeout, if it returns null then the timeout hit before the consumer could do its work.

    And since the java.util.concurrent classes are (supposed to be) automagically synchronized, no need to bother with manual sync.



  • I haven't looked into java.util till now. Will do though.
    Thanks for the help.
     



  • @nFec said:

    I haven't looked into java.util till now. Will do though.
    Thanks for the help.
     

    My pleasure, and sorry about the formatting I kinda forgot to put tags in my message, here's a readable version:

    1. Why are you using a custom container instead of a BlockingQueue (linked or array) from java.util.concurrent?
    2. In fact, since your application/problem seems to need only 1 item in the queue/container, I think you could use a pair of SynchronousQueues as a kind of message-passing system (or LinkedBlockingQueues if the producer can send more than one item to the consumer):
      • One SynchroneousQueue from the producer to the consumer, upon starting the consumer does a take on the SQ1 (will wait until the producer puts something on it), the consumer is the starting point of the second SQ.
      • The producer then puts your item on SQ1 (which the consumer will automatically retrieve and remove from the queue), then does a poll on the SQ2 with the timeout you want.
      • Upon completion of its work, the consumer will put something on SQ2 (anything that's not null)
      • Then it's very simple: if the producer's SQ2.poll() returns an object then the consumer ended its work before the timeout, if it returns null then the timeout hit before the consumer could do its work. And since the java.util.concurrent classes are (supposed to be) automagically synchronized, no need to bother with manual sync.


  • I agree with masklinn that using a custom container shouldn't be needed unless you're trying to use a data structure that isn't already provided in java (like maybe a B-Tree for example). 

    The problem I see is that  your container.wait is inside your synchronized block.  Is this just supposed to be like a Thread.sleep? Where the producer is just waiting until the consumer is done? If so, you don't want to do it that way.  If the producer is synced on the container while is waiting, then the consumer cant sync on it. 

     The cheap and easy way (maybe not the best) would be to just put a if (container.isEmpty()) before the sync block. That way it never locks on the container if its already full.

     

    I guess I need to figure out these tags things on here. 


     

     



  • Do your own homework.



  • @asuffield said:

    Do your own homework.

    If you think this is below your level just troll somewhere else. Thank you.

     

    The custom container is not the point here because it could be anything, a single object, whatever. It's just an example.
    I'll get back when i tried your hints.

    Thanks.
     



  • @nFec said:

    @asuffield said:

    Do your own homework.

    If you think this is below your level

    No, I think you're a lazy student.

    (Who is going to fail the exam because they didn't do their own homework) 



  • @asuffield said:

    No, I think you're a lazy student.

    (Who is going to fail the exam because they didn't do their own homework) 

    You do realize that this is the "Code related help & questions" forum? It's a place for asking things that one doesn't know. Suppose it was homework, why do you have an issue with asking for help with a specific problem? He doesn't want you to do his his work, he's obviously working on the problem himself, writing code to test his ideas, and when he ran into something he didn't understand he asked for someone with more knowledge on the subject to explain the matter.

    That's exactly what doing homework is supposed to be. 



  • @asuffield said:

    @nFec said:

    @asuffield said:

    Do your own homework.

    If you think this is below your level

    No, I think you're a lazy student.

    (Who is going to fail the exam because they didn't do their own homework) 

    lewl. I spend more time looking at framework notes and the references and generally googling bits like "VB.NET select case Fall-through" now than i did when i was learning in school.



  • @Nandurius said:

    @asuffield said:
    No, I think you're a lazy student.

    (Who is going to fail the exam because they didn't do their own homework) 

    You do realize that this is the "Code related help & questions" forum? It's a place for asking things that one doesn't know. Suppose it was homework, why do you have an issue with asking for help with a specific problem?

    This is more or less a stock question - it's likely to be in every course on concurrency, in one form or another. The purpose of the question is to make the student practice working out thread synchronisation problems for himself. Because he did not do this, he is going to be unable to solve the entirely different question that is on the exam paper.

    Knowing how to solve this particular problem is not the point. Students who fail to grasp this will fail.

    and when he ran into something he didn't understand he asked for
    someone with more knowledge on the subject to explain the matter.

    If that was really true then he should have asked his professor, who knows how much to explain without defeating the point of the homework, and how to ensure that the student learns the right things to pass the exam.

    It is never appropriate to ask how to solve homework questions here. Those questions always belong in class (or with a personal tutor). That is why you have classes. People who ask them here anyway should just drop out - places are limited and there's somebody else who could make better use of it. Wasteful students annoy me.



  • Who even told you this was homework?
    And if it was - what it isn't - they are right, i am not asking to solve my problem, but what a good way to achieve what i want is.
    And who tells you I'm from a country where i as supposedly lazy student would steal places from other to be students?

    But as this isn't homework...
    The code i posted is just some testing code, the context it is needed in is a huge webapp that I'm employed to work on.

    Yes I am a student, I had all the mutex, semaphore theory, I also know some things about java synchronisation. But what I know isn't enough to solve my problem.

    Like you sure know is that you can't just apply theory to practical things.
    And i dont like to reinvent the weel if it has already been implemented (like thes lock things).

     
    And now since it's the next workday for me since first posting this. I will read and hopefully learn about all the things the more helpful of posters told me about.
     

    If i got more questions i will ask again, and else ill post the final code that works for me.
    Thanks :)



  • Thanks your version with the Queues works great.

    regards. 


Log in to reply