简体   繁体   中英

Synchronizing multiple threads JAVA

I have 200 students waiting to enter a room with 200 seats (25 rows and 8 columns). The door capacity is 4 people. When a student enter the room, he chooses random seat (row and column). If the chosen seat is at 9th row or less it takes 1 second to sit, on 18th and less it takes 2 seconds, and if its from 18 to 25 it takes 3 seconds. When any of them take a seat another person must come in the room. The problem is that when the first 4 people enter the room they take seat one by one and not at once. How can I fix that? For example if 2 people choose a seat at 5th row they both need to sit for 1 seconds and two new students must enter the room.

public class Student 
{
int row;
int column;
volatile static int mutex;

//Generating random numbers for row and column
public Student(Seats[][] seats) 
{

    this.row = (int) Math.ceil(Math.random() * 25);
    this.column = (int) Math.ceil(Math.random() * 8);

    if (!seats[row][column].isTaken) 
    {
        seats[row][column].isTaken = true;
    } else 
    {
        do 
        {
            this.row = (int) Math.ceil(Math.random() * 25);
            this.column = (int) Math.ceil(Math.random() * 8);
        } while (!seats[row][column].isTaken);
        seats[row][column].isTaken = true;
    }
}

/*Check if the mutex is 4 (4 people are in the room) then wait
if someone enter the room increment mutex*/
synchronized void add() throws InterruptedException 
{
    while (mutex > 4)
        wait();
    Student.mutex++;

    notifyAll();
}

/* Check if mutex is 0 (no one is in the room) then wait
if the student has sit - decrement mutex and notify*/
synchronized void takeSeat() throws InterruptedException 
{
    while (mutex == 0)
        wait();
    Student.mutex--;
    notifyAll();

}
}

class Seats 
{
int seat;
boolean isTaken;

public Seats(int seat) 
{
    this.seat = seat;
    this.isTaken = false;
}
}


class StudentThread extends Thread 
{

Seats[][] seats = new Seats[25][8];

StudentThread(Seats[][] seats) 
{
    this.seats = seats;
}

public void run() 
{

    try 
    {
        Student student = new Student(seats);
        synchronized (seats) 
        {
            System.out.println("Student enter the room");

            /*call the synchronized method from student 
             that increment the mutex*/
            student.add();

            if (Student.mutex == 4) 
            {
                if (student.row <= 9) 
                {
                    sleep(1000);

                    student.takeSeat();

                    System.out.println("Student take a seat at "
                            + student.row + " " + student.column);
                }
                if (student.row <= 18 && student.row > 9) 
                {
                    sleep(2000);

                    student.takeSeat();

                    System.out.println("Student take a seat at "
                            + student.row + " " + student.column);
                }
                if (student.row <= 25 && student.row > 18) 
                {
                    sleep(3000);

                    student.takeSeat();

                    System.out.println("Student take a seat at "
                            + student.row + " " + student.column);
                }
            }
        }
    } catch (InterruptedException e) 
    {
        e.printStackTrace();
    }
}
}

class Main 
{

public static void main(String[] args) 
{

    Seats[][] seats = new Seats[25][8];

    //Initializing the seats
    for (int i = 0; i < 25; i++)
        for (int j = 0; j < 8; j++) 
        {
            seats[i][j] = new Seats(i);
        }

    for (int i = 0; i < 200; i++) 
    {
        StudentThread T1 = new StudentThread(seats);
        T1.start();
    }
}
}

Use a Semaphore , they are very practical for these kind of things.

To make the example a bit more realistic: imagine you need to do 200 HTTP get-requests, but the server will ban you if you run more than 4 requests at the same time. The example below shows how you can limit the number of requests running at the same time using a Semaphore.

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class ResourceUsageLimiter {

    static ExecutorService executor = Executors.newCachedThreadPool();
    static int requests = 20;
    static int maxRequestsConcurrent = 4; 
    static int maxRequestTime = 1000;
    static Random randomizer = new Random();
    static Semaphore openSlots = new Semaphore(maxRequestsConcurrent);
    static long startTime = System.currentTimeMillis();

    public static void main(String[] args) {

        try {
            for (int i = 0; i < requests; i++) {
                openSlots.acquire();
                executor.execute(new RequestRunner(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }

    static long time() {
        return System.currentTimeMillis() - startTime;
    }

    static class RequestRunner implements Runnable {

        int sleepTime, reqId;

        public RequestRunner(int reqId) {
            this.reqId = reqId;
            sleepTime = randomizer.nextInt(maxRequestTime);
        }

        @Override
        public void run() {

            try {
                System.out.println(time() + " " + reqId + " sleeping " + sleepTime);
                Thread.sleep(sleepTime);
                System.out.println(time() + " " + reqId + " sleep done");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                openSlots.release();
            }
        }

    }

}

Ofcourse, another way to limit the maximum number of requests running at the same time in the example is to use a thread pool with a fixed size of 4.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM