簡體   English   中英

同步多線程JAVA

[英]Synchronizing multiple threads JAVA

我有200名學生正在等待進入有200個座位(25行8列)的房間。 門容量為4人。 當學生進入房間時,他會選擇隨機座位(行和列)。 如果選擇的座位排在第9排或以下,則需要1秒鍾才能坐下;排在18排及以下,則需要2秒鍾;如果座位排在18到25之間,則需要3秒鍾。 當他們中的任何一個坐下時,另一個人必須進入房間。 問題在於,當前四個人進入房間時,他們一個人坐在一個座位上,而不是一次坐下。 我該如何解決? 例如,如果有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();
    }
}
}

使用信號量 ,它們對於這類事情非常實用。

為了使示例更實際:假設您需要執行200個HTTP get-request,但是如果您同時運行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的線程池。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM