как выполнить 2 потока одновременно с помощью семафора

#java #multithreading #semaphore

#java #многопоточность #семафор

Вопрос:

я создал 2 потока для 2 поездов, первый имеет направление (север-юг), а второй — направление (юг-север), поэтому есть только одна железная дорога, не могу встретить 2 поезда с разным направлением .. итак, вот мой основной класс :

  public static void main(String[] args) throws InterruptedException {        
        Semaphore sem = new Semaphore(1); 
 
        MyThread train1 = new MyThread(sem, "nord-sud"); 
        MyThread train2 = new MyThread(sem, "sud-nord"); 
         
        // stating threads 1 and train 2 
        train1.start(); 
        train2.start(); 
        train1.join();       
        train2.join();
    }
 

и вот мой класс MyThread расширенный класс потоков :

 class MyThread extends Thread 
{ 
    Semaphore sem; 
    String threadName; 
    public MyThread(Semaphore sem, String threadName)  
    { 
        super(threadName); 
        this.sem = sem; 
        this.threadName = threadName; 
    } 
  
    @Override
    public void run() { 
          
        // run by thread A 
        if(this.getName().equals("nord-sud")) 
        { 
            System.out.println("Starting "   threadName); 
            try 
            { 
                System.out.println(threadName   " wait for railway to enter"); 
              
                // acquiring the lock 
                sem.acquire(); 
              
                System.out.println(threadName   " have access to enter"); 
          
                // Now, accessing the shared resource. 
                // other waiting threads will wait, until this  
                // thread release the lock 
                for(int i=0; i < 5; i  ) 
                { 
                    Shared.count  ; 
                    System.out.println(threadName   ": "   i); 
          
                    // Now, allowing a context switch -- if possible. 
                    // for thread B to execute 
                    Thread.sleep(1000); 
                } 
            } catch (InterruptedException exc) { 
                    System.out.println(exc); 
                } 
          
                // Release the permit. 
                
                System.out.println(threadName   " left the railway "); 
                sem.release(); 
                
                
        } 
          
        // run by thread B 
        else
        { 
            System.out.println("Starting "   threadName); 
            try 
            { 
                // First, get a permit. 
                System.out.println(threadName   " wait for railway to enter"); 
              
          
                sem.acquire(); 
              
                System.out.println(threadName   " have access to enter"); 
          
                for(int i=0; i < 5; i  ) 
                { 
                    Shared.count--; 
                    System.out.println(threadName   ": "   i); 
          
              
                    Thread.sleep(1000); 
                } 
            } catch (InterruptedException exc) { 
                    System.out.println(exc); 
                } 
                // Release the permit. 
                System.out.println(threadName   "left the railway"); 
                sem.release();
        } 
    } 
   
}
 

поэтому, когда я добавляю 2 поезда с направлением север-юг, например, за тот же период, я хочу, чтобы они оба получили ввод на железную дорогу, потому что у них одинаковое направление, поезд должен ждать только тогда, когда он поймет, что другой поезд с другим направлением находится на железной дороге. итак, как я могу выполнить 2 потока одновременно? например, train1 (nord-sud), train2 (nord-sud) и train3 (sud-nord). таким образом, как поезд 1, так и поезд 2 входят в железнодорожный, а поезд 3 ждет, пока они уйдут, чтобы получить доступ.

Комментарии:

1. Почему if... else... блок? Вы запускаете точно такой же код в обеих ветвях.

Ответ №1:

Вы можете создать два разрешения для поездов с одинаковыми направлениями и одно разрешение для поездов с разными направлениями, например:

 public class Solution0 {
public static void main(String[] args) throws InterruptedException {
    String direction1 = "nord-sud";
    String direction2 = "sud-sud";
    int permissionCount;
    if (direction1.equals(direction2)){
        permissionCount = 2;
    }else {
        permissionCount = 1;
    }
    Semaphore sem = new Semaphore(permissionCount);

    MyThread train1 = new MyThread(sem, direction1);
    MyThread train2 = new MyThread(sem, direction2);

    // stating threads 1 and train 2
    train1.start();
    train2.start();
    train1.join();
    train2.join();
}
 

}

вывод для другого направления:

 Starting sud-sud
Starting nord-sud
sud-sud wait for railway to enter
nord-sud wait for railway to enter
sud-sud have access to enter
sud-sud: 0
sud-sud: 1
sud-sud: 2
sud-sud: 3
sud-sud: 4
sud-sudleft the railway
nord-sud have access to enter
nord-sud: 0
nord-sud: 1
nord-sud: 2
nord-sud: 3
nord-sud: 4
nord-sud left the railway
 

вывод для аналогичного направления:

 Starting sud-sud
Starting sud-sud
sud-sud wait for railway to enter
sud-sud wait for railway to enter
sud-sud have access to enter
sud-sud have access to enter
sud-sud: 0
sud-sud: 0
sud-sud: 1
sud-sud: 1
sud-sud: 2
sud-sud: 2
sud-sud: 3
sud-sud: 3
sud-sud: 4
sud-sud: 4
sud-sudleft the railway
sud-sudleft the railway
 

Комментарии:

1. да, но что, если я добавлю 2 поезда с тем же направлением, а затем другой поезд с другим направлением? я хочу, чтобы третий также получил доступ, когда 2 первых поезда покинули железную дорогу.

Ответ №2:

В этом случае вы должны создать список и поток для каждого из поездов nord-sud и sud-nord. Потоки списка должны отвечать за получение семафора, затем при получении они должны запускать отдельные потоки поездов (предположительно, добавляя задержку с каждым после первого, чтобы поезда не запускались одновременно). Затем поток списка должен вызывать Thread.join() в каждом потоке поезда (хотя на самом деле может потребоваться присоединиться только к последнему), а затем освободить семафор после прибытия последнего поезда.