1114. Print in Order
leetcode easy
Task
Предположим, у нас есть класс:
public class Foo {
public void first() { print("first"); }
public void second() { print("second"); }
public void third() { print("third"); }
}
Один и тот же экземпляр Foo будет передан трем разным потокам. Поток A вызовет first(), поток B вызовет second(), и поток C вызовет third(). Спроектируйте механизм и модифицируйте программу, чтобы гарантировать, что second() выполняется после first(), а third() выполняется после second().
Примечание:
Мы не знаем, как потоки будут планироваться в операционной системе, даже если числа в вводе подразумевают порядок выполнения. Формат ввода, который вы видите, в основном предназначен для обеспечения полноты наших тестов.
Пример:
Input: nums = [1,2,3]
Output: "firstsecondthird"
Explanation: There are three threads being fired asynchronously. The input [1,2,3] means thread A calls first(), thread B calls second(), and thread C calls third(). "firstsecondthird" is the correct output.
C# solution
matched/originalusing System;
using System.Threading;
public class Foo {
private SemaphoreSlim firstJobDone = new SemaphoreSlim(0, 1);
private SemaphoreSlim secondJobDone = new SemaphoreSlim(0, 1);
public void First(Action printFirst) {
printFirst();
firstJobDone.Release();
}
public void Second(Action printSecond) {
firstJobDone.Wait();
printSecond();
secondJobDone.Release();
}
public void Third(Action printThird) {
secondJobDone.Wait();
printThird();
}
}C++ solution
auto-draft, review before submit#include <bits/stdc++.h>
using namespace std;
// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
public class Foo {
private SemaphoreSlim firstJobDone = new SemaphoreSlim(0, 1);
private SemaphoreSlim secondJobDone = new SemaphoreSlim(0, 1);
public void First(Action printFirst) {
printFirst();
firstJobDone.Release();
}
public void Second(Action printSecond) {
firstJobDone.Wait();
printSecond();
secondJobDone.Release();
}
public void Third(Action printThird) {
secondJobDone.Wait();
printThird();
}
}Java solution
matched/originalclass Foo {
private AtomicInteger firstJobDone = new AtomicInteger(0);
private AtomicInteger secondJobDone = new AtomicInteger(0);
public Foo() {}
public void first(Runnable printFirst) throws InterruptedException {
printFirst.run();
firstJobDone.incrementAndGet();
}
public void second(Runnable printSecond) throws InterruptedException {
while (firstJobDone.get() != 1) {
}
printSecond.run();
secondJobDone.incrementAndGet();
}
public void third(Runnable printThird) throws InterruptedException {
while (secondJobDone.get() != 1) {
}
printThird.run();
}
}Python solution
matched/originalfrom threading import Semaphore
class Foo:
def __init__(self):
self.firstJobDone = Semaphore(0)
self.secondJobDone = Semaphore(0)
def first(self, printFirst):
printFirst()
self.firstJobDone.release()
def second(self, printSecond):
self.firstJobDone.acquire()
printSecond()
self.secondJobDone.release()
def third(self, printThird):
self.secondJobDone.acquire()
printThird()Go solution
matched/originalpackage main
import (
"sync"
)
type Foo struct {
firstJobDone sync.Mutex
secondJobDone sync.Mutex
}
func NewFoo() *Foo {
f := &Foo{}
f.firstJobDone.Lock()
f.secondJobDone.Lock()
return f
}
func (f *Foo) First(printFirst func()) {
printFirst()
f.firstJobDone.Unlock()
}
func (f *Foo) Second(printSecond func()) {
f.firstJobDone.Lock()
printSecond()
f.firstJobDone.Unlock()
f.secondJobDone.Unlock()
}
func (f *Foo) Third(printThird func()) {
f.secondJobDone.Lock()
printThird()
f.secondJobDone.Unlock()
}Explanation
Algorithm
1⃣Инициализация переменных:
Инициализируйте координационные переменные firstJobDone и secondJobDone, чтобы указать, что задания еще не выполнены.
2⃣Функция first():
В этой функции нет зависимости, поэтому можно сразу приступить к выполнению задания. В конце функции обновите переменную firstJobDone, чтобы указать, что первое задание выполнено.
3⃣Функции second() и third():
В функции second() проверьте статус firstJobDone. Если она не обновлена, подождите, иначе переходите к выполнению второго задания. В конце функции обновите переменную secondJobDone, чтобы отметить завершение второго задания.
В функции third() проверьте статус secondJobDone. Аналогично функции second(), подождите сигнала secondJobDone перед тем, как приступить к выполнению третьего задания.
😎