1

I'm In a sticky situation. I know this is almost as far as i can get for now, but what i want to do is actually to make an array of thread (or many thread) and accommodate number of threads in queue in the line, so for example i can accommodate 3 thread at a time, i make the first 3 thread run, then make the other wait, when there is free like for example the 1 is free or terminated the other one can start running.

also i want to make sure if the thread can run or not if the thread that is running is the same as the other thread's gender.

    Thread myThreads[] = new Thread[LN.GetLine().length()];
    int l=LN.GetLine().length();
    for (int j = 0; j < LN.GetLine().length(); j++) {
    String Name = CR.Gender(LN.GetLine().charAt(j)) + j;
    myThreads[j] = new Thread(new MyThread(Name,LN));
    myThreads[j].setPriority(l);
    System.out.println(myThreads[j].toString());
    l--;
    }
    for(int b=0;b<LN.GetLine().length();b++){
        myThreads[b].start();
        synchronized(myThreads[b]){
            try{
              myThreads[b].wait();     
        }catch(InterruptedException e){
            e.printStackTrace();
        }

        }

        }

For now what i can make is accommodate or make 1 thread run at a time.

(Yes this is a Machine bathroom Problem)

My real question is. if i Edit the function run() in myThread() that has a wait() or just plain put a System.out.println(getName() + " is Using"); And how will the thread know in their run() function that other thread is running.

 public class MyThread extends Thread {
 public MyThread(String id) {
 super(id);
 }
 public void run(){
 System.out.println(getName() + " is Using");
 >>>Put wait if other thread running<<<<
 >>>If can use or not if same gender<<<<
 }

Or should i just implement that outside? or put the Waiting outside? Also i'm really new in Threading so i haven't really explored with Sleep and Interrupt yet.

HerlDerp
  • 47
  • 1
  • 1
  • 11
  • 1
    Calling `wait()` on a thread is unusual and in this case, it doesn't have any effect. – Titus Oct 01 '16 at 14:24
  • Yes i know that by this time i tried it... Anyway i can't kill/stop a thread, because that would mean they can't use, maybe if i can make all the thread wait, and stay wait. until i resume them if they are able to use. – HerlDerp Oct 01 '16 at 14:36
  • Consider using a fixed-thread-pool ExecutorService (in your case, the pool size would be 3). This technique will not require the creation of threads that wait (wasteful of resources). ref: https://docs.oracle.com/javase/7/docs/api/index.html?java/util/concurrent/ExecutorService.html – StvnBrkdll Oct 01 '16 at 14:54
  • @mangotang: if he wants to run one thread at a time sequentially, the size of the thread pool should be 0, not 3. – Hovercraft Full Of Eels Oct 02 '16 at 14:31
  • 1
    @Hovercraft he *seemed* to say he wanted 3 of the threads running simultaneously, maybe I misunderstood (" i make the first 3 thread run"). If OP wants one thread, then a single-thread-pool executor should work. A thread pool of size 0 will cause the newFixedThreadPool() factory method to throw an IllegalArgumentException. The size needs to be > 0. ref: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int) – StvnBrkdll Oct 02 '16 at 18:18
  • @mangotang: oops, I meant `1`! Easily obtained via `Executors.newSingleThreadExecutor()` – Hovercraft Full Of Eels Oct 02 '16 at 18:19

3 Answers3

0

You can do this without wait.

Here is an example:

public class MyThread extends Thread {
    static final Object gender1Lock = new Object();
    static final Object gender2Lock = new Object();
    int gender;
    public MyThread(String id, int gender) {
        super(id);
        this.gender = gender;
    }
    public void run(){
        System.out.println(getName() + " is waiting");
        if(gender == 1){
            synchronized(gender1Lock){ // ocupy gender 1
                System.out.println(getName() + " is Using");
            }
        }else if(gender == 2){
            synchronized(gender1Lock){ // ocupy gender 2
                System.out.println(getName() + " is Using");
            }
        }
    }
}

Since only one thread can synchronize on an object at a time it means that only one thread of a given gender can run at a time. This creates sequential execution of all threads of a given gender.

And here is an example of using this kind of thread.

for(int i = 0; i < 20; i++){
    new MyThread("Person " + i, (i%2 == 0) ? 1 : 2).start();
}
Titus
  • 22,031
  • 1
  • 23
  • 33
  • Maybe I'm confused, but wouldn't gender1Lock and gender2Lock need to be static in this situation? And wouldn't we want to implement Runnable, and not extend Thread? And what about using some type of stack or a ... – Hovercraft Full Of Eels Oct 01 '16 at 14:54
  • 1
  • @HovercraftFullOfEels Yes, I've just realized that myself (the `static` thing). – Titus Oct 01 '16 at 14:54
  • @HovercraftFullOfEels The OP seems to be just getting started with all this. I was trying to make this as simple as possible. – Titus Oct 01 '16 at 14:56
  • I think it does make sense. and also i didn't really expound that it's only one bathroom being used by both gender (unisex bathroom) which why there is also answer that consider 2 bathroom, it's my mistake. oh well. – HerlDerp Oct 01 '16 at 15:43
  • @HerlDerp If that is the case, you can change this example to use only one object as a lock instead of 2. – Titus Oct 01 '16 at 15:46
  • Tried it but not the output i think it should be. – HerlDerp Oct 11 '16 at 12:22
0

I would just use two single thread executors obtained via Executors.newSingleThreadExecutor();, one for each gender, and then submit the task to the appropriate executor. Simple and done.

And if you only have one bathroom, then only one executor is needed. For example:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class GetInLine {
    public static void main(String[] args) {
        List<MyRunnable> myRunnables = new ArrayList<>();
        myRunnables.add(new MyRunnable("Bob", false));
        myRunnables.add(new MyRunnable("Jill", true));
        myRunnables.add(new MyRunnable("Frank", false));
        myRunnables.add(new MyRunnable("Amy", true));
        myRunnables.add(new MyRunnable("Pete", false));
        myRunnables.add(new MyRunnable("Diane", true));        

        ExecutorService myExecutor = Executors.newSingleThreadExecutor();
        for (MyRunnable myRunnable : myRunnables) {
            myExecutor.submit(myRunnable);
        }

        myExecutor.shutdown();
    }
}

public class MyRunnable implements Runnable {
    private static final int MIN_SLEEP_TIME = 500;
    private static final int MAX_SLEEP_TIME = 2000;
    private static final int FEMALE_SLEEP_BONUS = 500;
    private Random random = new Random();
    private String name;
    private boolean female;

    public MyRunnable(String name, boolean female) {
        this.name = name;
        this.female = female;
    }

    public String getName() {
        return name;
    }

    public boolean isFemale() {
        return female;
    }

    @Override
    public void run() {
        System.out.println(name + " is using");
        try {
            long sleepTime = MIN_SLEEP_TIME + random.nextInt(MAX_SLEEP_TIME - MIN_SLEEP_TIME);
            if (female) {
                sleepTime += FEMALE_SLEEP_BONUS;
            }
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {}
        System.out.println(name + " is done");
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

... so for example i can accommodate 3 thread at a time, i make the first 3 thread run, then make the other wait, when there is free like for example the 1 is free or terminated the other one can start running.

This can be achieved using a Executor with a fixed Thread Pool.

 ExecutorService m = Executors.newFixedThreadPool(3)
 ExecutorService f = Executors.newFixedThreadPool(3)
 for(;;) {
    Object o = new Object();
    m.execute(() -> {...; o.wait(); /* You know notify was called on o at this point hence f run clause is running or has just run */ ...})
    f.execute(() -> {...; o.notify(); ...})
 }

Since this a a batroom the ques are seperate an there will be fixed number of toilets:

 ExecutorService m = Executors.newFixedThreadPool(3)
 ExecutorService f = Executors.newFixedThreadPool(3)
 for(;;) {
    Person male = getNextMale();
    m.execute(() -> {...; /* do something with male */  ...})

    Person female = getNextFemale();
    f.execute(() -> {...; /* do something with female */ ...})
 }

To implement the queue you can use one of the BlockingQueue implementations.