同步多个线程JAVA

时间:2014-12-06 09:34:53

标签: java multithreading

我有200名学生在等待进入一个有200个座位(25行和8列)的房间。门容量为4人。当学生进入房间时,他选择随机座位(行和列)。如果所选择的座位在第9行或更少,则需要1秒钟才能坐下,在18日,少于2秒,如果从18到25,则需要3秒。 当他们中的任何人坐下时,另一个人必须进入房间。 问题是,当前4个人进入房间时,他们一个接一个地坐下,而不是一次。我该如何解决这个问题? 例如,如果2人选择第5排座位,则他们都需要坐1秒钟,并且必须有两名新生进入房间。

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();
    }
}
}

1 个答案:

答案 0 :(得分:1)

使用Semaphore,它们对于这类事物非常实用。

为了使示例更加真实:假设您需要执行200个HTTP get-requests,但如果您同时运行4个以上的请求,服务器将禁止您。下面的示例显示了如何使用信号量限制同时运行的请求数。

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();
            }
        }

    }

}

当然,在示例中限制同时运行的最大请求数的另一种方法是使用固定大小为4的线程池。