diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5e2eb7c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +**.idea +**/out +**.iml diff --git a/lab-02/.gitignore b/lab-02/.gitignore new file mode 100644 index 0000000..df1a13b --- /dev/null +++ b/lab-02/.gitignore @@ -0,0 +1 @@ +/logs \ No newline at end of file diff --git a/lab-02/lab-02.iml b/lab-02/lab-02.iml new file mode 100644 index 0000000..0cbebe4 --- /dev/null +++ b/lab-02/lab-02.iml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lab-02/log_example/README.txt b/lab-02/log_example/README.txt new file mode 100644 index 0000000..611b51d --- /dev/null +++ b/lab-02/log_example/README.txt @@ -0,0 +1,2 @@ +Логи работают странно, в самом начале вставляют какой-то сценарий из буффера. +Настоящие начинаются со слов "Start of program" \ No newline at end of file diff --git a/lab-02/log_example/log-2023-12-10-22-00-n1.log b/lab-02/log_example/log-2023-12-10-22-00-n1.log new file mode 100644 index 0000000..bce92bb --- /dev/null +++ b/lab-02/log_example/log-2023-12-10-22-00-n1.log @@ -0,0 +1,349 @@ +2023-12-10 22:00:00.956 [Thread-1] INFO ShipGenerator - Ship PCB is on the horizon +2023-12-10 22:00:00.960 [Thread-10196] INFO Tunnel - Ship PCB entered the tunnel +2023-12-10 22:00:01.562 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:01.562 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:01.562 [Thread-10196] INFO Ship - Ship PCB exit the tunnel +2023-12-10 22:00:01.562 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:01.562 [Thread-0] INFO Dock - Ship PCB entered the dock +2023-12-10 22:00:01.563 [Thread-0] INFO Dock - Ship PCB with SLAVES is unloading... +2023-12-10 22:00:01.563 [Thread-0] INFO Dock - SLAVES storage is full +2023-12-10 22:00:01.563 [Thread-0] INFO Dock - Ship PCB leaves the dock +2023-12-10 22:00:01.563 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:01.563 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:01.563 [Thread-10196] INFO Ship - Ship PCB disappears on the horizon +2023-12-10 22:00:03.968 [Thread-1] INFO ShipGenerator - Ship PCC is on the horizon +2023-12-10 22:00:03.969 [Thread-10197] INFO Tunnel - Ship PCC entered the tunnel +2023-12-10 22:00:04.574 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:04.574 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:04.574 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:04.574 [Thread-0] INFO Dock - Ship PCC entered the dock +2023-12-10 22:00:04.574 [Thread-0] INFO Dock - Ship PCC with SLAVES is unloading... +2023-12-10 22:00:04.574 [Thread-0] INFO Dock - SLAVES storage is full +2023-12-10 22:00:04.574 [Thread-0] INFO Dock - Ship PCC leaves the dock +2023-12-10 22:00:04.575 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:04.575 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:04.574 [Thread-10197] INFO Ship - Ship PCC exit the tunnel +2023-12-10 22:00:06.983 [Thread-1] INFO ShipGenerator - Ship PCD is on the horizon +2023-12-10 22:00:06.984 [Thread-10198] INFO Tunnel - Ship PCD entered the tunnel +2023-12-10 22:00:07.575 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:07.575 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:07.575 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:07.575 [Thread-0] INFO Dock - Ship PCD entered the dock +2023-12-10 22:00:07.575 [Thread-0] INFO Dock - Ship PCD with WEAPON is unloading... +2023-12-10 22:00:07.576 [Thread-0] INFO Dock - WEAPON storage is full +2023-12-10 22:00:07.576 [Thread-0] INFO Dock - Ship PCD leaves the dock +2023-12-10 22:00:07.576 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:07.575 [Thread-10198] INFO Ship - Ship PCD exit the tunnel +2023-12-10 22:00:07.576 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:10.012 [Thread-1] INFO ShipGenerator - Ship PCE is on the horizon +2023-12-10 22:00:10.066 [Thread-10199] INFO Tunnel - Ship PCE entered the tunnel +2023-12-10 22:00:10.585 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:10.586 [Thread-10199] INFO Ship - Ship PCE exit the tunnel +2023-12-10 22:00:10.586 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:10.587 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:10.587 [Thread-0] INFO Dock - Ship PCE entered the dock +2023-12-10 22:00:10.587 [Thread-0] INFO Dock - Ship PCE with SLAVES is unloading... +2023-12-10 22:00:10.587 [Thread-0] INFO Dock - SLAVES storage is full +2023-12-10 22:00:10.587 [Thread-0] INFO Dock - Ship PCE leaves the dock +2023-12-10 22:00:10.587 [Thread-10199] INFO Ship - Ship PCE disappears on the horizon +2023-12-10 22:00:10.587 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:10.588 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:13.025 [Thread-1] INFO ShipGenerator - Ship PCF is on the horizon +2023-12-10 22:00:13.028 [Thread-10200] INFO Tunnel - Ship PCF entered the tunnel +2023-12-10 22:00:13.594 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:13.594 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:13.594 [Thread-10200] INFO Ship - Ship PCF exit the tunnel +2023-12-10 22:00:13.594 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:13.595 [Thread-0] INFO Dock - Ship PCF entered the dock +2023-12-10 22:00:13.595 [Thread-0] INFO Dock - Ship PCF with RAW_MATERIALS is unloading... +2023-12-10 22:00:13.595 [Thread-0] INFO Dock - RAW_MATERIALS storage is full +2023-12-10 22:00:13.595 [Thread-0] INFO Dock - Ship PCF leaves the dock +2023-12-10 22:00:13.595 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:13.595 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:13.595 [Thread-10200] INFO Ship - Ship PCF disappears on the horizon +2023-12-10 22:00:16.037 [Thread-1] INFO ShipGenerator - Ship PCG is on the horizon +2023-12-10 22:00:16.039 [Thread-10201] INFO Tunnel - Ship PCG entered the tunnel +2023-12-10 22:00:16.603 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:16.603 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:16.603 [Thread-10201] INFO Ship - Ship PCG exit the tunnel +2023-12-10 22:00:16.603 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:16.604 [Thread-0] INFO Dock - Ship PCG entered the dock +2023-12-10 22:00:16.604 [Thread-0] INFO Dock - Ship PCG with WEAPON is unloading... +2023-12-10 22:00:16.604 [Thread-0] INFO Dock - WEAPON storage is full +2023-12-10 22:00:16.604 [Thread-0] INFO Dock - Ship PCG leaves the dock +2023-12-10 22:00:16.604 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:16.604 [Thread-10201] INFO Ship - Ship PCG disappears on the horizon +2023-12-10 22:00:16.604 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:19.042 [Thread-1] INFO ShipGenerator - Ship PCH is on the horizon +2023-12-10 22:00:19.043 [Thread-10202] INFO Tunnel - Ship PCH entered the tunnel +2023-12-10 22:00:19.607 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:19.610 [Thread-10202] INFO Ship - Ship PCH exit the tunnel +2023-12-10 22:00:19.611 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:19.612 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:19.613 [Thread-0] INFO Dock - Ship PCH entered the dock +2023-12-10 22:00:19.613 [Thread-0] INFO Dock - Ship PCH with SLAVES is unloading... +2023-12-10 22:00:19.613 [Thread-0] INFO Dock - SLAVES storage is full +2023-12-10 22:00:19.613 [Thread-0] INFO Dock - Ship PCH leaves the dock +2023-12-10 22:00:19.613 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:19.613 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:19.614 [Thread-10202] INFO Ship - Ship PCH disappears on the horizon +2023-12-10 22:00:22.043 [Thread-1] INFO ShipGenerator - Ship PCI is on the horizon +2023-12-10 22:00:22.045 [Thread-10203] INFO Tunnel - Ship PCI entered the tunnel +2023-12-10 22:00:22.644 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:22.654 [Thread-10203] INFO Ship - Ship PCI exit the tunnel +2023-12-10 22:00:22.654 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:22.666 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:22.666 [Thread-0] INFO Dock - Ship PCI entered the dock +2023-12-10 22:00:22.666 [Thread-0] INFO Dock - Ship PCI with FOOD is unloading... +2023-12-10 22:00:22.667 [Thread-0] INFO Dock - FOOD storage is full +2023-12-10 22:00:22.667 [Thread-0] INFO Dock - Ship PCI leaves the dock +2023-12-10 22:00:22.683 [Thread-10203] INFO Ship - Ship PCI disappears on the horizon +2023-12-10 22:00:22.683 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:22.684 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:25.058 [Thread-1] INFO ShipGenerator - Ship PCJ is on the horizon +2023-12-10 22:00:25.064 [Thread-10204] INFO Tunnel - Ship PCJ entered the tunnel +2023-12-10 22:00:25.685 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:25.685 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:25.685 [Thread-10204] INFO Ship - Ship PCJ exit the tunnel +2023-12-10 22:00:25.685 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:25.686 [Thread-0] INFO Dock - Ship PCJ entered the dock +2023-12-10 22:00:25.686 [Thread-0] INFO Dock - Ship PCJ with SLAVES is unloading... +2023-12-10 22:00:25.686 [Thread-0] INFO Dock - SLAVES storage is full +2023-12-10 22:00:25.686 [Thread-0] INFO Dock - Ship PCJ leaves the dock +2023-12-10 22:00:25.686 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:25.686 [Thread-10204] INFO Ship - Ship PCJ disappears on the horizon +2023-12-10 22:00:25.686 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:28.066 [Thread-1] INFO ShipGenerator - Ship PCK is on the horizon +2023-12-10 22:00:28.068 [Thread-10205] INFO Tunnel - Ship PCK entered the tunnel +2023-12-10 22:00:28.698 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:28.698 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:28.698 [Thread-10205] INFO Ship - Ship PCK exit the tunnel +2023-12-10 22:00:28.699 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:28.699 [Thread-0] INFO Dock - Ship PCK entered the dock +2023-12-10 22:00:28.700 [Thread-0] INFO Dock - Ship PCK with FOOD is unloading... +2023-12-10 22:00:28.700 [Thread-0] INFO Dock - FOOD storage is full +2023-12-10 22:00:28.700 [Thread-0] INFO Dock - Ship PCK leaves the dock +2023-12-10 22:00:28.700 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:28.700 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:28.700 [Thread-10205] INFO Ship - Ship PCK disappears on the horizon +2023-12-10 22:00:31.070 [Thread-1] INFO ShipGenerator - Ship PCL is on the horizon +2023-12-10 22:00:31.072 [Thread-10206] INFO Tunnel - Ship PCL entered the tunnel +2023-12-10 22:00:31.706 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:31.708 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:31.708 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:31.708 [Thread-0] INFO Dock - Ship PCL entered the dock +2023-12-10 22:00:31.708 [Thread-0] INFO Dock - Ship PCL with FOOD is unloading... +2023-12-10 22:00:31.724 [Thread-0] INFO Dock - FOOD storage is full +2023-12-10 22:00:31.725 [Thread-0] INFO Dock - Ship PCL leaves the dock +2023-12-10 22:00:31.725 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:31.726 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:31.708 [Thread-10206] INFO Ship - Ship PCL exit the tunnel +2023-12-10 22:00:34.080 [Thread-1] INFO ShipGenerator - Ship PCM is on the horizon +2023-12-10 22:00:34.081 [Thread-10207] INFO Tunnel - Ship PCM entered the tunnel +2023-12-10 22:00:34.727 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:34.728 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:34.728 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:34.728 [Thread-10207] INFO Ship - Ship PCM exit the tunnel +2023-12-10 22:00:34.728 [Thread-0] INFO Dock - Ship PCM entered the dock +2023-12-10 22:00:34.730 [Thread-0] INFO Dock - Ship PCM with CHEMICAL is unloading... +2023-12-10 22:00:34.730 [Thread-0] INFO Dock - CHEMICAL storage is full +2023-12-10 22:00:34.730 [Thread-0] INFO Dock - Ship PCM leaves the dock +2023-12-10 22:00:34.730 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:34.730 [Thread-10207] INFO Ship - Ship PCM disappears on the horizon +2023-12-10 22:00:34.730 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:37.095 [Thread-1] INFO ShipGenerator - Ship PCN is on the horizon +2023-12-10 22:00:37.097 [Thread-10208] INFO Tunnel - Ship PCN entered the tunnel +2023-12-10 22:00:37.740 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:37.741 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:37.741 [Thread-10208] INFO Ship - Ship PCN exit the tunnel +2023-12-10 22:00:37.741 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:37.741 [Thread-0] INFO Dock - Ship PCN entered the dock +2023-12-10 22:00:37.741 [Thread-0] INFO Dock - Ship PCN with RAW_MATERIALS is unloading... +2023-12-10 22:00:37.741 [Thread-0] INFO Dock - RAW_MATERIALS storage is full +2023-12-10 22:00:37.742 [Thread-0] INFO Dock - Ship PCN leaves the dock +2023-12-10 22:00:37.742 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:37.742 [Thread-10208] INFO Ship - Ship PCN disappears on the horizon +2023-12-10 22:00:37.742 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:40.108 [Thread-1] INFO ShipGenerator - Ship PCO is on the horizon +2023-12-10 22:00:40.110 [Thread-10209] INFO Tunnel - Ship PCO entered the tunnel +2023-12-10 22:00:40.743 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:40.743 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:40.743 [Thread-10209] INFO Ship - Ship PCO exit the tunnel +2023-12-10 22:00:40.744 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:40.744 [Thread-0] INFO Dock - Ship PCO entered the dock +2023-12-10 22:00:40.744 [Thread-0] INFO Dock - Ship PCO with FOOD is unloading... +2023-12-10 22:00:40.744 [Thread-0] INFO Dock - FOOD storage is full +2023-12-10 22:00:40.744 [Thread-0] INFO Dock - Ship PCO leaves the dock +2023-12-10 22:00:40.744 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:40.744 [Thread-10209] INFO Ship - Ship PCO disappears on the horizon +2023-12-10 22:00:40.745 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:43.114 [Thread-1] INFO ShipGenerator - Ship PCP is on the horizon +2023-12-10 22:00:43.116 [Thread-10210] INFO Tunnel - Ship PCP entered the tunnel +2023-12-10 22:00:43.749 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:43.749 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:43.749 [Thread-10210] INFO Ship - Ship PCP exit the tunnel +2023-12-10 22:00:43.749 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:43.750 [Thread-0] INFO Dock - Ship PCP entered the dock +2023-12-10 22:00:43.750 [Thread-0] INFO Dock - Ship PCP with CHEMICAL is unloading... +2023-12-10 22:00:43.750 [Thread-0] INFO Dock - CHEMICAL storage is full +2023-12-10 22:00:43.750 [Thread-0] INFO Dock - Ship PCP leaves the dock +2023-12-10 22:00:43.750 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:43.750 [Thread-10210] INFO Ship - Ship PCP disappears on the horizon +2023-12-10 22:00:43.750 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:45.512 [main] INFO Main - Start of program. +2023-12-10 22:00:45.555 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:45.559 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:45.566 [Thread-2] INFO Hobo - This is an ingredients storage: +2023-12-10 22:00:45.568 [Thread-2] INFO Hobo - +--------------- +| 0 | 0 | 0 | +--------------- +2023-12-10 22:00:45.569 [Thread-2] INFO Hobo - It consists of bread, grain, pizza +2023-12-10 22:00:45.570 [Thread-2] INFO HoboTent - Day 0 +2023-12-10 22:00:45.572 [Thread-2] INFO Hobo - Sviatoslav has materialized from garbage +2023-12-10 22:00:45.578 [Thread-2] INFO Hobo - Dobrojir has materialized from blood +2023-12-10 22:00:45.579 [Thread-2] INFO Hobo - Tihomir has materialized from ashes +2023-12-10 22:00:45.581 [Thread-2] INFO Hobo - Ratibor has materialized from puddle on the asphalt +2023-12-10 22:00:45.586 [Thread-4] INFO Hobo - Dobrojir steals +2023-12-10 22:00:45.587 [Thread-4] INFO Hobo - +--------------- +| 0 | 0 | 0 | +--------------- +2023-12-10 22:00:45.588 [Thread-5] INFO Hobo - Tihomir cooks +2023-12-10 22:00:45.586 [Thread-3] INFO Hobo - Sviatoslav steals +2023-12-10 22:00:45.589 [Thread-5] INFO Hobo - Tihomir is waiting for ingredients... +2023-12-10 22:00:45.592 [Thread-6] INFO Hobo - Ratibor cooks +2023-12-10 22:00:46.116 [Thread-1] INFO ShipGenerator - Ship PCQ is on the horizon +2023-12-10 22:00:46.117 [Thread-10211] INFO Tunnel - Ship PCQ entered the tunnel +2023-12-10 22:00:46.764 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:46.764 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:46.764 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:46.764 [Thread-10211] INFO Ship - Ship PCQ exit the tunnel +2023-12-10 22:00:46.764 [Thread-0] INFO Dock - Ship PCQ entered the dock +2023-12-10 22:00:46.765 [Thread-0] INFO Dock - Ship PCQ with CHEMICAL is unloading... +2023-12-10 22:00:46.765 [Thread-0] INFO Dock - CHEMICAL storage is full +2023-12-10 22:00:46.765 [Thread-0] INFO Dock - Ship PCQ leaves the dock +2023-12-10 22:00:46.765 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:46.765 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:46.765 [Thread-10211] INFO Ship - Ship PCQ disappears on the horizon +2023-12-10 22:00:47.589 [Thread-4] INFO Hobo - Dobrojir stole bread +2023-12-10 22:00:47.590 [Thread-4] INFO Hobo - +--------------- +| 1 | 0 | 0 | +--------------- +2023-12-10 22:00:47.592 [Thread-3] INFO Hobo - Sviatoslav stole bread +2023-12-10 22:00:47.592 [Thread-6] INFO Hobo - Ratibor is waiting for ingredients... +2023-12-10 22:00:48.563 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:48.563 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:48.572 [Thread-1] INFO ShipGenerator - Ship A is on the horizon +2023-12-10 22:00:48.572 [Thread-7] INFO Tunnel - Ship A entered the tunnel +2023-12-10 22:00:49.127 [Thread-1] INFO ShipGenerator - Ship PCR is on the horizon +2023-12-10 22:00:49.128 [Thread-10212] INFO Tunnel - Ship PCR entered the tunnel +2023-12-10 22:00:49.594 [Thread-6] INFO Hobo - Ratibor is waiting for ingredients... +2023-12-10 22:00:49.594 [Thread-4] INFO Hobo - Dobrojir stole grain +2023-12-10 22:00:49.594 [Thread-3] INFO Hobo - Sviatoslav stole grain +2023-12-10 22:00:49.594 [Thread-4] INFO Hobo - +--------------- +| 2 | 1 | 0 | +--------------- +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - Ship PCR entered the dock +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - Ship PCR with WEAPON is unloading... +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - WEAPON storage is full +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - Ship PCR leaves the dock +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:49.767 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:49.767 [Thread-10212] INFO Ship - Ship PCR exit the tunnel +2023-12-10 22:00:51.575 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:51.575 [Thread-1] INFO ShipGenerator - Ship B is on the horizon +2023-12-10 22:00:51.575 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:51.576 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:51.576 [Thread-7] INFO Ship - Ship A exit the tunnel +2023-12-10 22:00:51.576 [Thread-8] INFO Tunnel - Ship B entered the tunnel +2023-12-10 22:00:51.576 [Thread-0] INFO Dock - Ship A entered the dock +2023-12-10 22:00:51.577 [Thread-0] INFO Dock - Ship A with CHEMICAL is unloading... +2023-12-10 22:00:51.577 [Thread-0] INFO Dock - The ship A is unloading... +2023-12-10 22:00:51.605 [Thread-4] INFO Hobo - Dobrojir stole pizza +2023-12-10 22:00:51.605 [Thread-5] INFO Hobo - Tihomir is waiting for ingredients... +2023-12-10 22:00:51.605 [Thread-3] INFO Hobo - Sviatoslav stole pizza +2023-12-10 22:00:51.605 [Thread-3] INFO Hobo - Sviatoslav finished working +2023-12-10 22:00:51.605 [Thread-4] INFO Hobo - Dobrojir finished working +2023-12-10 22:00:52.137 [Thread-1] INFO ShipGenerator - Ship PCS is on the horizon +2023-12-10 22:00:52.149 [Thread-10213] INFO Tunnel - Ship PCS entered the tunnel +2023-12-10 22:00:52.768 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:52.768 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:52.768 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:52.768 [Thread-10213] INFO Ship - Ship PCS exit the tunnel +2023-12-10 22:00:52.768 [Thread-0] INFO Dock - Ship PCS entered the dock +2023-12-10 22:00:52.768 [Thread-0] INFO Dock - Ship PCS with CHEMICAL is unloading... +2023-12-10 22:00:52.769 [Thread-0] INFO Dock - CHEMICAL storage is full +2023-12-10 22:00:52.769 [Thread-0] INFO Dock - Ship PCS leaves the dock +2023-12-10 22:00:52.769 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:52.769 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:52.769 [Thread-10213] INFO Ship - Ship PCS disappears on the horizon +2023-12-10 22:00:53.606 [Thread-5] INFO Hobo - Tihomir finished working +2023-12-10 22:00:53.606 [Thread-6] INFO Hobo - Ratibor is waiting for ingredients... +2023-12-10 22:00:54.584 [Thread-0] INFO Dock - The ship A is unloading... +2023-12-10 22:00:54.584 [Thread-1] INFO ShipGenerator - Ship C is on the horizon +2023-12-10 22:00:54.585 [Thread-9] INFO Tunnel - Ship C entered the tunnel +2023-12-10 22:00:55.160 [Thread-1] INFO ShipGenerator - Ship PCT is on the horizon +2023-12-10 22:00:55.160 [Thread-10214] INFO Tunnel - Ship PCT entered the tunnel +2023-12-10 22:00:55.615 [Thread-6] INFO Hobo - Ratibor finished working +2023-12-10 22:00:55.615 [Thread-6] INFO HoboTent - All came from work. The feast has begun. There are 0 sandwiches on the table +2023-12-10 22:00:55.616 [Thread-2] INFO HoboTent - Ratibor died from hunger +2023-12-10 22:00:55.616 [Thread-2] INFO HoboTent - Tihomir ate Sviatoslav +2023-12-10 22:00:55.616 [Thread-2] INFO HoboTent - Dobrojir is hungry +2023-12-10 22:00:55.616 [Thread-2] INFO HoboTent - The feast is over +2023-12-10 22:00:55.617 [Thread-2] INFO HoboTent - Day 1 +2023-12-10 22:00:55.617 [Thread-2] INFO Hobo - Dobrinya has materialized from dust +2023-12-10 22:00:55.617 [Thread-2] INFO Hobo - Tishilo has materialized from blood +2023-12-10 22:00:55.617 [Thread-5] INFO Hobo - Tihomir cooks +2023-12-10 22:00:55.617 [Thread-4] INFO Hobo - Dobrojir steals +2023-12-10 22:00:55.618 [Thread-10] INFO Hobo - Dobrinya steals +2023-12-10 22:00:55.618 [Thread-5] INFO Hobo - Tihomir is waiting for ingredients... +2023-12-10 22:00:55.618 [Thread-11] INFO Hobo - Tishilo cooks +2023-12-10 22:00:55.618 [Thread-10] INFO Hobo - +--------------- +| 2 | 2 | 2 | +--------------- +2023-12-10 22:00:55.770 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:55.771 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:55.771 [Thread-10214] INFO Ship - Ship PCT exit the tunnel +2023-12-10 22:00:55.771 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:55.771 [Thread-0] INFO Dock - Ship PCT entered the dock +2023-12-10 22:00:55.771 [Thread-0] INFO Dock - Ship PCT with CHEMICAL is unloading... +2023-12-10 22:00:55.772 [Thread-0] INFO Dock - CHEMICAL storage is full +2023-12-10 22:00:55.772 [Thread-0] INFO Dock - Ship PCT leaves the dock +2023-12-10 22:00:55.772 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:55.772 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:55.772 [Thread-10214] INFO Ship - Ship PCT disappears on the horizon +2023-12-10 22:00:57.586 [Thread-0] INFO Dock - The ship A is unloading... +2023-12-10 22:00:57.586 [Thread-1] INFO ShipGenerator - Ship D is on the horizon +2023-12-10 22:00:57.588 [Thread-12] INFO Tunnel - Ship D entered the tunnel +2023-12-10 22:00:57.619 [Thread-10] INFO Hobo - Dobrinya stole pizza +2023-12-10 22:00:57.620 [Thread-10] INFO Hobo - +--------------- +| 2 | 2 | 3 | +--------------- +2023-12-10 22:00:57.633 [Thread-11] INFO Hobo - Tishilo started cooking! +2023-12-10 22:00:57.633 [Thread-4] INFO Hobo - Dobrojir stole pizza +2023-12-10 22:00:58.161 [Thread-1] INFO ShipGenerator - Ship PCU is on the horizon +2023-12-10 22:00:58.162 [Thread-10215] INFO Tunnel - Ship PCU entered the tunnel +2023-12-10 22:00:58.775 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:58.775 [Thread-0] INFO Dock - There is a response +2023-12-10 22:00:58.775 [Thread-0] INFO Dock - Dock ready for ship unloading +2023-12-10 22:00:58.775 [Thread-0] INFO Dock - Ship PCU entered the dock +2023-12-10 22:00:58.775 [Thread-0] INFO Dock - Ship PCU with FOOD is unloading... +2023-12-10 22:00:58.775 [Thread-10215] INFO Ship - Ship PCU exit the tunnel +2023-12-10 22:00:58.775 [Thread-0] INFO Dock - FOOD storage is full +2023-12-10 22:00:58.776 [Thread-0] INFO Dock - Ship PCU leaves the dock +2023-12-10 22:00:58.776 [Thread-0] INFO Dock - Dock calls +2023-12-10 22:00:58.776 [Thread-0] INFO Dock - There is no response, wait a little... +2023-12-10 22:00:59.635 [Thread-4] INFO Hobo - Dobrojir stole bread +2023-12-10 22:00:59.635 [Thread-10] INFO Hobo - Dobrinya stole bread +2023-12-10 22:00:59.635 [Thread-10] INFO Hobo - +--------------- +| 2 | 0 | 1 | +--------------- diff --git a/lab-02/resources/config.json b/lab-02/resources/config.json new file mode 100644 index 0000000..97afeda --- /dev/null +++ b/lab-02/resources/config.json @@ -0,0 +1,20 @@ +{ + "generating_time" : 3, + "ship_capacity_min" : 10, + "ship_capacity_max" : 100, + "cargo_types" : [ + "CHEMICAL", + "FOOD", + "WEAPON", + "RAW_MATERIALS", + "SLAVES" + ], + "max_ships" : 3, + "unloading_speed" : 10, + "dock_capacity" : 50, + "hobos" : 4, + "ingredients_count" : [2, 2, 3], + "stealing_time" : 2, + "crimes_per_day" : 3, + "cooking_time": 10 +} \ No newline at end of file diff --git a/lab-02/resources/log4j2.xml b/lab-02/resources/log4j2.xml new file mode 100644 index 0000000..5fcb704 --- /dev/null +++ b/lab-02/resources/log4j2.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/lab-02/resources/names.txt b/lab-02/resources/names.txt new file mode 100644 index 0000000..2c9e0dd --- /dev/null +++ b/lab-02/resources/names.txt @@ -0,0 +1,4 @@ +Sviatoslav Dobrojir Tihomir Ratibor Dobrinya Tishilo +Naum Bogdan Borislav Dobrojir Zvenislav Yaropolk +Svetozar Mirolyub Bogomil Vsemysl Dobrovlad +Kazimir Luchezar Milomir Unislav Snovid Jidobor \ No newline at end of file diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/Dock.java b/lab-02/src/by/waitingsolong/docks_and_hobos/Dock.java new file mode 100644 index 0000000..4fff569 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/Dock.java @@ -0,0 +1,100 @@ +package by.waitingsolong.docks_and_hobos; + +import by.waitingsolong.docks_and_hobos.helpers.CargoType; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantLock; + +public class Dock implements Runnable { + private static final Logger logger = LogManager.getLogger(Dock.class); + private final int unloading_speed; + private final int dock_capacity; + private volatile Map storage = new ConcurrentHashMap<>(); + private final Tunnel tunnel; + private final long recallDelay; + private final Thread thread; + public Dock(int unloadingSpeed, int dockCapacity, Tunnel tunnel, long recallDelay) { + this.unloading_speed = unloadingSpeed; + this.dock_capacity = dockCapacity; + this.tunnel = tunnel; + this.thread = new Thread(this); + this.recallDelay = recallDelay; + for (CargoType cargoType : CargoType.values()) { + storage.put(cargoType, 0); + } + } + + @Override + public void run() { + while (!thread.isInterrupted()) { + logger.info("Dock calls"); + Optional call = tunnel.call(); + if (call.isPresent()) { + logger.info("There is a response"); + processShip(call.get()); + } else { + logger.info("There is no response, wait a little..."); + try { + Thread.sleep(recallDelay * 1000); + } catch (InterruptedException e) { + logger.error("Dock is interrupted during sleep", e); + return; + } + } + } + } + + + public void processShip(Ship ship) { + logger.info("Dock ready for ship unloading"); + ReentrantLock wakeUpLock = ship.getWakeUpLock(); + wakeUpLock.lock(); + + logger.info("Ship " + ship.getName() + " entered the dock"); + synchronized (ship) { + unload(ship); + + logger.info("Ship " + ship.getName() + " leaves the dock"); + ship.notify(); + } + } + + private void unload(Ship ship) { + CargoType cargoType = ship.getCargoType(); + + logger.info("Ship " + ship.getName() + " with " + cargoType.getName() + " is unloading..."); + while (true) { + int unloaded = ship.unload(unloading_speed); + if (unloaded == 0) { + return; + } + + int become = storage.get(cargoType) + unloaded; + if (become < dock_capacity) { + storage.put(cargoType, become); + } else { + storage.put(cargoType, dock_capacity); + logger.info(cargoType.getName() + " storage is full"); + return; + } + + Thread.yield(); + + logger.info("The ship " + ship.getName() + " is unloading..."); + try { + Thread.sleep(recallDelay * 1000); + } catch(InterruptedException e) { + logger.error("Unloading of ship is interrupted"); + Thread.currentThread().interrupt(); + } + } + } + + public void start() { + thread.start(); + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/Hobo.java b/lab-02/src/by/waitingsolong/docks_and_hobos/Hobo.java new file mode 100644 index 0000000..435a004 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/Hobo.java @@ -0,0 +1,205 @@ +package by.waitingsolong.docks_and_hobos; + +import by.waitingsolong.docks_and_hobos.helpers.Job; +import by.waitingsolong.docks_and_hobos.helpers.State; +import by.waitingsolong.docks_and_hobos.helpers.NameDistributor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; + +public class Hobo implements Runnable { + private static final Logger logger = LogManager.getLogger(Hobo.class); + private final String name; + private final HoboTent tent; + private final Thread thread; + private Optional job = Optional.empty(); + private static final List materializationSources = Arrays.asList("ashes", "sewage", "blood", "dust", "pile of stones", "shipwreck", "garbage", "puddle on the asphalt", "rotten food leftovers"); + private static final List ingredientNames = Arrays.asList("bread", "grain", "pizza", "sauce", "cheese", "tomatos"); + private State state; + private static Random random = new Random(); + private boolean reportingThief; + + public Hobo(HoboTent hoboTent) { + this.thread = new Thread(this); + this.name = NameDistributor.getUniqueName(); + this.tent = hoboTent; + this.state = new State(); + String materializationSource = materializationSources.get(random.nextInt(materializationSources.size())); + logger.info(this.name + " has materialized from " + materializationSource); + if (HoboTent.ingredientsStorage.length() > ingredientNames.size()) { + throw new RuntimeException("Provide more names to Hobo.ingredientNames or reduce ingredients_count size"); + } + } + + public void setJob(Job job) { + this.job = Optional.ofNullable(job); + } + + @Override + public void run() { + while (!thread.isInterrupted()) { + try { + tent.getSemaphore().acquire(); + } catch (InterruptedException e) { + logger.error(name + " interrupted while acquiring semaphore to start working"); + Thread.currentThread().interrupt(); + } + tent.getSemaphore().release(); + if (job.isPresent()) { + switch (job.get()) { + case Cook -> cook(); + case Thief -> steal(); + } + } + logger.info(name + " finished working"); + tent.getWorkPhaser().arriveAndAwaitAdvance(); + eat(); + tent.getFeastBarrier().await(); + try { + tent.getSemaphore().acquire(); + tent.getSemaphore().release(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + private void eat() { + AtomicInteger atrociouslyLongSandwiches = tent.getAtrociouslyLongSandwiches(); + if (atrociouslyLongSandwiches.get() > 0) { + atrociouslyLongSandwiches.decrementAndGet(); + state.hunger = false; + logger.info(name + " got sandwich"); + } else { + state.hunger = true; + } + } + + public String getName() { + return this.name; + } + + private void cook() { + logger.info(name + " cooks"); + while (tent.getThiefsAreDone().get() > 0) { + AtomicIntegerArray storage = HoboTent.ingredientsStorage; + boolean enoughIngredients = true; + + synchronized (storage) { + for (int i = 0; i < storage.length(); i++) { + if (storage.get(i) < tent.getIngredientsCount().get(i)) { + enoughIngredients = false; + break; + } + } + + if (enoughIngredients) { + logger.info(name + " started cooking!"); + for (int i = 0; i < storage.length(); i++) { + storage.getAndAdd(i, -tent.getIngredientsCount().get(i)); + } + try { + Thread.sleep( 1000L * tent.getCookingTime()); + } catch(InterruptedException e) { + logger.error(name + " interrupted while cooking"); + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + tent.getAtrociouslyLongSandwiches().incrementAndGet(); + logger.info(name + " made a sandwich"); + } else { + logger.info(name + " is waiting for ingredients..."); + try { + Thread.sleep(tent.getStealing_time() * 1000L); + } catch(InterruptedException e) { + logger.error(name + " interrupted while waiting ingredients"); + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } + } + } + } + + + private void steal() { + logger.info(name + " steals"); + int counter = 0; + while (counter++ != tent.getCrimes_per_day()) { + if (reportingThief) { + logIngredientsStorage(); + } + + AtomicIntegerArray storage = HoboTent.ingredientsStorage; + int ingredientIndex = HoboTent.pickDeficitIngredient(); + try { + Thread.sleep(tent.getStealing_time() * 1000L); + } catch(InterruptedException e) { + logger.error(name + " interrupted while stealing"); + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + logger.info(name + " stole " + ingredientNames.get(ingredientIndex)); + storage.getAndIncrement(ingredientIndex); + } + if (reportingThief) reportingThief = false; + tent.getThiefsAreDone().decrementAndGet(); + } + + private static void logIngredientsStorage() { + AtomicIntegerArray ingredientsStorage = HoboTent.ingredientsStorage; + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + for (int i = 0; i < ingredientsStorage.length() * 5; i++) { + sb.append("-"); + } + sb.append("\n| "); + for (int i = 0; i < ingredientsStorage.length(); i++) { + sb.append(ingredientsStorage.get(i)); + if (i < ingredientsStorage.length() - 1) { + sb.append(" | "); + } + } + sb.append(" |\n"); + for (int i = 0; i < ingredientsStorage.length() * 5; i++) { + sb.append("-"); + } + logger.info(sb.toString()); + } + + static void presentIngredientsStorage() { + logger.info("This is an ingredients storage:"); + logIngredientsStorage(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < HoboTent.ingredientsStorage.length(); i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(ingredientNames.get(i)); + } + logger.info("It consists of " + sb.toString()); + } + + void die() { + state.dead = true; + } + + void interrupt() { + thread.interrupt(); + } + + public void start() { + thread.start(); + } + + public State getState() { + return state; + } + + public void setReportingThief(boolean reportingThief) { + this.reportingThief = reportingThief; + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/HoboTent.java b/lab-02/src/by/waitingsolong/docks_and_hobos/HoboTent.java new file mode 100644 index 0000000..3b726e4 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/HoboTent.java @@ -0,0 +1,218 @@ +package by.waitingsolong.docks_and_hobos; + +import java.util.*; +import java.util.concurrent.Phaser; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; + +import by.waitingsolong.docks_and_hobos.custom.CyclicBarrier; +import by.waitingsolong.docks_and_hobos.custom.Semaphore; +import by.waitingsolong.docks_and_hobos.helpers.Job; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class HoboTent implements Runnable { + private static final Logger logger = LogManager.getLogger(HoboTent.class); + private final int hobos; + private final int stealing_time; + private final int crimes_per_day; + private final int cooking_time; + private static ArrayList ingredients_count; + private final Phaser workPhaser; + private Semaphore semaphore; + private final CyclicBarrier feastBarrier; + private final List hoboList = new ArrayList<>(); + private final AtomicInteger atrociouslyLongSandwiches = new AtomicInteger(0); + public static AtomicIntegerArray ingredientsStorage; + private final Thread thread; + private AtomicInteger thiefsAreDone; + private static Random random = new Random(); + + public HoboTent(int hobos, int stealing_time, int crimes_per_day, int cooking_time, ArrayList ingredients_count) { + if (hobos <= 2) { + throw new IllegalArgumentException("Number of hobos must be greater than 2"); + } + this.semaphore = new Semaphore(1); + this.hobos = hobos; + this.stealing_time = stealing_time; + this.crimes_per_day = crimes_per_day; + this.cooking_time = cooking_time; + HoboTent.ingredients_count = ingredients_count; + this.workPhaser = new Phaser(hobos + 1) { + @Override + protected boolean onAdvance(int phase, int registeredParties) { + logger.info("All came from work. The feast has begun. There are " + atrociouslyLongSandwiches.get() + " sandwiches on the table"); + return super.onAdvance(phase, registeredParties); + } + }; + this.feastBarrier = new CyclicBarrier(hobos + 1); + this.thread = new Thread(this); + this.thiefsAreDone = new AtomicInteger(0); + HoboTent.ingredientsStorage = new AtomicIntegerArray(ingredients_count.size()); + } + + // semaphore guarantee that HoboTent will be executed first after the feast + @Override + public void run() { + Hobo.presentIngredientsStorage(); + + try { + semaphore.acquire(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + + while (!thread.isInterrupted()) { + logger.info("Day " + workPhaser.getPhase()); + mobilization(); + Collections.shuffle(hoboList); + distributeJobs(); + semaphore.release(); + workPhaser.arriveAndAwaitAdvance(); + try { + semaphore.acquire(); + } catch (InterruptedException e) { + logger.info("Nonsense."); + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + feastBarrier.await(); + handleStates(); + logger.info("The feast is over"); + } + } + + private void mobilization() { + while (hoboList.size() < hobos) { + Hobo hobo = new Hobo(this); + hoboList.add(hobo); + hobo.start(); + } + } + + private void distributeJobs() { + int cooks = 0; + int thiefs = 0; + for (int i = 0; i < hoboList.size(); i++) { + Hobo hobo = hoboList.get(i); + if (i < 2) { + hobo.setJob(Job.Cook); + cooks++; + } else if (i == 3){ + hobo.setJob(Job.Thief); + hobo.setReportingThief(true); + thiefs++; + } + else { + hobo.setJob(Job.Thief); + thiefs++; + } + } + assert(cooks + thiefs == hobos); + thiefsAreDone.set(thiefs); + } + + void handleStates() { + List hobosToRemove = new ArrayList<>(); + for (Hobo hobo : hoboList) { + if (!hobo.getState().dead && hobo.getState().hunger) { + double chance = Math.random(); + if (chance < 0.25) { + hobosToRemove.add(hobo); + hobo.die(); + logger.info(hobo.getName() + " died from hunger"); + } else if (chance < 0.5) { + Hobo eatenHobo = getRandomHobo(); + hobosToRemove.add(eatenHobo); + eatenHobo.die(); + logger.info(hobo.getName() + " ate " + eatenHobo.getName()); + } else { + logger.info(hobo.getName() + " is hungry"); + } + } + } + + hoboList.removeAll(hobosToRemove); + for (Hobo hobo : hobosToRemove) { + hobo.interrupt(); + } + } + + public Phaser getWorkPhaser() { + return workPhaser; + } + + public ArrayList getIngredientsCount() { + return ingredients_count; + } + + public int getStealing_time() { + return stealing_time; + } + + public int getCookingTime() { + return cooking_time; + } + + public Semaphore getSemaphore() { + return semaphore; + } + + public void start() { + thread.start(); + } + + public AtomicInteger getAtrociouslyLongSandwiches() { + return atrociouslyLongSandwiches; + } + public synchronized Hobo getRandomHobo() { + if (hoboList.isEmpty()) { + throw new RuntimeException("No hobos in HoboTent"); + } + return hoboList.get(random.nextInt(hoboList.size())); + } + + public CyclicBarrier getFeastBarrier() { + return feastBarrier; + } + + public int getCrimes_per_day() { + return crimes_per_day; + } + + public AtomicInteger getThiefsAreDone() { + return thiefsAreDone; + } + + public static int pickIngredientProportionally() { + int totalWeight = 0; + for (int i = 0; i < ingredients_count.size(); i++) { + totalWeight += ingredients_count.get(i); + } + int randomNum = random.nextInt(totalWeight); + int cumulativeWeight = 0; + int ingredientIndex = -1; + for (int i = 0; i < ingredients_count.size(); i++) { + cumulativeWeight += ingredients_count.get(i); + if (randomNum < cumulativeWeight) { + ingredientIndex = i; + break; + } + } + return ingredientIndex; + } + + public static int pickDeficitIngredient() { + int minShareIndex = -1; + double minShare = Double.MAX_VALUE; + for (int i = 0; i < ingredientsStorage.length(); i++) { + double currShare = (double) ingredientsStorage.get(i) / ingredients_count.get(i); + if (currShare < minShare) { + minShare = currShare; + minShareIndex = i; + } + } + return minShareIndex; + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/Main.java b/lab-02/src/by/waitingsolong/docks_and_hobos/Main.java new file mode 100644 index 0000000..4b95a31 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/Main.java @@ -0,0 +1,78 @@ +package by.waitingsolong.docks_and_hobos; + +import by.waitingsolong.docks_and_hobos.helpers.CargoType; +import by.waitingsolong.docks_and_hobos.helpers.Config; +import by.waitingsolong.docks_and_hobos.helpers.NameDistributor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.json.JSONException; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; + +public class Main { + private static final Logger logger = LogManager.getLogger(Main.class); + + public static void main(String[] args) { + logger.info("Start of program."); + + String configPath; + if (args.length == 0) { + Path path = Paths.get("resources", "config.json"); + configPath = path.toString(); + } else { + configPath = args[0]; + } + + Config config; + + int max_ships; + int ship_capacity_min; + int ship_capacity_max; + int generating_time; + int unloading_speed; + int dock_capacity; + int hobos; + int stealing_time; + int crimes_per_day; + int cooking_time; + ArrayList ingredients_count; + ArrayList cargo_types; + + try { + config = new Config(configPath); + + max_ships = config.get("max_ships"); + ship_capacity_max = config.get("ship_capacity_max"); + ship_capacity_min = config.get("ship_capacity_min"); + generating_time = config.get("generating_time"); + unloading_speed = config.get("unloading_speed"); + dock_capacity = config.get("dock_capacity"); + hobos = config.get("hobos"); + ingredients_count = config.get("ingredients_count"); + stealing_time = config.get("stealing_time"); + crimes_per_day = config.get("crimes_per_day"); + cooking_time = config.get("cooking_time"); + cargo_types = config.get("cargo_types"); + + } catch (JSONException | IOException e) { + logger.error("Error to parse json"); + throw new RuntimeException("Error to parse json"); + } + + CargoType.setTypes(cargo_types); + NameDistributor.readUniqueNames(Paths.get("resources", "names.txt").toString()); + + Tunnel tunnel = new Tunnel(max_ships); + Dock dock = new Dock(unloading_speed, dock_capacity, tunnel, generating_time); + ShipGenerator shipGenerator = new ShipGenerator(generating_time, ship_capacity_min, ship_capacity_max, tunnel); + HoboTent hoboTent = new HoboTent(hobos, stealing_time, crimes_per_day, cooking_time, ingredients_count); + + dock.start(); + shipGenerator.start(); + hoboTent.start(); + } + +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/Ship.java b/lab-02/src/by/waitingsolong/docks_and_hobos/Ship.java new file mode 100644 index 0000000..5edb082 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/Ship.java @@ -0,0 +1,86 @@ +package by.waitingsolong.docks_and_hobos; + +import java.util.concurrent.atomic.AtomicInteger; + +import by.waitingsolong.docks_and_hobos.helpers.CargoType; +import by.waitingsolong.docks_and_hobos.helpers.NameDistributor; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import java.util.concurrent.locks.ReentrantLock; + +public class Ship implements Runnable { + private int capacity; + private final CargoType cargoType; + private final String name; + private static final Logger logger = LogManager.getLogger(Ship.class); + private static final AtomicInteger shipCount = new AtomicInteger(0); + private final Tunnel tunnel; + private final Thread thread; + private final ReentrantLock wakeUpLock; + + public Ship(int capacity, CargoType cargoType, Tunnel tunnel) { + this.capacity = capacity; + this.cargoType = cargoType; + this.name = NameDistributor.getCounterName(shipCount.getAndIncrement()); + this.tunnel = tunnel; + this.thread = new Thread(this); + this.wakeUpLock = new ReentrantLock(); + } + + public void start() { + thread.start(); + } + + @Override + public void run() { + tunnel.enter(this); + wakeUpLock.lock(); + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) { + logger.info("Ship " + name + " has sunk"); + Thread.currentThread().interrupt(); + return; + } + finally { + wakeUpLock.unlock(); + } + } + logger.info("Ship " + this.name + " exit the tunnel"); + + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) { + logger.error("Ship " + name + " is interrupted in the dock", e); + Thread.currentThread().interrupt(); + } + } + + logger.info("Ship " + name + " vanished into thin air"); + thread.interrupt(); + } + + public int unload(int units) { + if (capacity < units) { + int given = capacity; + capacity = 0; + return given; + } + else { + capacity -= units; + return units; + } + } + + public String getName() { + return name; + } + + public CargoType getCargoType() { + return cargoType; + } + + public ReentrantLock getWakeUpLock() { return wakeUpLock; } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/ShipGenerator.java b/lab-02/src/by/waitingsolong/docks_and_hobos/ShipGenerator.java new file mode 100644 index 0000000..4abc159 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/ShipGenerator.java @@ -0,0 +1,46 @@ +package by.waitingsolong.docks_and_hobos; + +import by.waitingsolong.docks_and_hobos.helpers.CargoType; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Random; + +public class ShipGenerator implements Runnable { + private static final Logger logger = LogManager.getLogger(ShipGenerator.class); + private final int generating_time; + private final int ship_capacity_min; + private final int ship_capacity_max; + private final Tunnel tunnel; + private final Thread thread; + private static final Random random = new Random(); + + public ShipGenerator(int generating_time, int ship_capacity_min, int ship_capacity_max, Tunnel tunnel) { + this.generating_time = generating_time; + this.ship_capacity_min = ship_capacity_min; + this.ship_capacity_max = ship_capacity_max; + this.thread = new Thread(this); + this.tunnel = tunnel; + } + + @Override + public void run() { + while (!thread.isInterrupted()) { + try { + Thread.sleep(generating_time * 1000); + int capacity = ship_capacity_min + random.nextInt(ship_capacity_max - ship_capacity_min + 1); + CargoType cargoType = CargoType.getRandom(); + Ship ship = new Ship(capacity, cargoType, tunnel); + logger.info("Ship " + ship.getName() + " is on the horizon"); + ship.start(); + } catch (InterruptedException e) { + logger.error("Ship generator is interrupted", e); + Thread.currentThread().interrupt(); + } + } + } + + public void start() { + thread.start(); + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/Tunnel.java b/lab-02/src/by/waitingsolong/docks_and_hobos/Tunnel.java new file mode 100644 index 0000000..4e0a2d1 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/Tunnel.java @@ -0,0 +1,38 @@ +package by.waitingsolong.docks_and_hobos; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Optional; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class Tunnel { + private static final Logger logger = LogManager.getLogger(Tunnel.class); + private final BlockingQueue tunnel; + + public Tunnel(int maxShips) { + this.tunnel = new LinkedBlockingQueue<>(maxShips); + } + + public void enter(Ship ship) { + if (!tunnel.offer(ship)) { + logger.info("Ship " + ship.getName() + " has not entered the tunnel"); + Thread.currentThread().interrupt(); + } else { + logger.info("Ship " + ship.getName() + " entered the tunnel"); + } + } + + public Optional call() { + Ship ship = tunnel.poll(); + if (ship != null) { + synchronized (ship) { + ship.notify(); + } + return Optional.of(ship); + } else { + return Optional.empty(); + } + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/custom/CyclicBarrier.java b/lab-02/src/by/waitingsolong/docks_and_hobos/custom/CyclicBarrier.java new file mode 100644 index 0000000..6182fce --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/custom/CyclicBarrier.java @@ -0,0 +1,49 @@ +package by.waitingsolong.docks_and_hobos.custom; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +public class CyclicBarrier { + private final int parties; + private static int generation = 0; + private int waiting = 0; + private final ReentrantLock lock = new ReentrantLock(); + private final Condition condition = lock.newCondition(); + private final Runnable barrierAction; + + public CyclicBarrier(int parties) { + this.parties = parties; + this.barrierAction = null; + } + + public CyclicBarrier(int parties, Runnable barrierAction) { + this.parties = parties; + this.barrierAction = barrierAction; + } + + public void await() { + lock.lock(); + try { + waiting++; + if (waiting == parties) { + if (barrierAction != null) { + barrierAction.run(); + } + waiting = 0; + generation++; + condition.signalAll(); + } else { + int currGeneration = generation; + while (waiting < parties && generation == currGeneration) { + condition.await(); + } + } + } catch(InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } finally { + lock.unlock(); + } + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/custom/Semaphore.java b/lab-02/src/by/waitingsolong/docks_and_hobos/custom/Semaphore.java new file mode 100644 index 0000000..5a44554 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/custom/Semaphore.java @@ -0,0 +1,73 @@ +package by.waitingsolong.docks_and_hobos.custom; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +public class Semaphore { + private int permits; + private boolean fair; + private ReentrantLock lock; + private Condition condition; + + public Semaphore(int permits, boolean fair) { + this.permits = permits; + this.fair = fair; + this.lock = new ReentrantLock(fair); + this.condition = lock.newCondition(); + } + + public Semaphore(int permits) { + this(permits, false); + } + + public void acquire() throws InterruptedException { + lock.lock(); + try { + while (permits == 0) { + condition.await(); + } + permits--; + } finally { + lock.unlock(); + } + } + + public void acquireUninterruptibly() { + lock.lock(); + try { + while (permits == 0) { + condition.awaitUninterruptibly(); + } + permits--; + } finally { + lock.unlock(); + } + } + + public boolean tryAcquire() { + + lock.lock(); + try { + if (permits > 0) { + permits--; + return true; + } else { + return false; + } + } finally { + lock.unlock(); + } + } + + public void release() { + lock.lock(); + try { + permits++; + condition.signal(); + } finally { + lock.unlock(); + } + } +} + + diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/CargoType.java b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/CargoType.java new file mode 100644 index 0000000..8a64b73 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/CargoType.java @@ -0,0 +1,54 @@ +package by.waitingsolong.docks_and_hobos.helpers; + +import java.util.*; + +public class CargoType { + private static final Random random = new Random(); + private static List types; + + public static void setTypes(List types_) { + types = types_; + + } + private int id; + + public CargoType(int id) { + if (id < 0 || id >= types.size()) { + throw new IllegalArgumentException("Invalid CargoType id: " + id); + } + this.id = id; + } + + public static List values() { + List cargoTypes = new ArrayList<>(); + for (int i = 0; i < types.size(); i++) { + cargoTypes.add(new CargoType(i)); + } + return cargoTypes; + } + + public String getName() { + return types.get(id); + } + + public static CargoType getRandom() { + return new CargoType(random.nextInt(types.size())); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + CargoType cargoType = (CargoType) obj; + return id == cargoType.id; + } + + @Override + public int hashCode() { + return Objects.hash(id); + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/Config.java b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/Config.java new file mode 100644 index 0000000..d5c8c8f --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/Config.java @@ -0,0 +1,34 @@ +package by.waitingsolong.docks_and_hobos.helpers; + +import org.json.*; + +import java.io.IOException; +import java.nio.file.*; +import java.util.ArrayList; + +public class Config { + private JSONObject config; + + public Config(String path) throws IOException, JSONException { + String content = new String(Files.readAllBytes(Paths.get(path))); + this.config = new JSONObject(content); + } + + public T get(String key) throws JSONException { + if (!this.config.has(key)) { + throw new IllegalArgumentException("No such key in config.json: " + key); + } + Object value = this.config.get(key); + if (value instanceof JSONArray) { + JSONArray array = (JSONArray) value; + ArrayList list = new ArrayList<>(); + for (int i = 0; i < array.length(); i++) { + list.add(array.get(i)); + } + return (T) list; + } + return (T) value; + } + + +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/Job.java b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/Job.java new file mode 100644 index 0000000..0c30862 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/Job.java @@ -0,0 +1,6 @@ +package by.waitingsolong.docks_and_hobos.helpers; + +public enum Job { + Thief, + Cook +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/NameDistributor.java b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/NameDistributor.java new file mode 100644 index 0000000..cd3390c --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/NameDistributor.java @@ -0,0 +1,45 @@ +package by.waitingsolong.docks_and_hobos.helpers; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class NameDistributor { + private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + private static List uniqueNames = new ArrayList<>(); + private static int currUniqueNameIndex = 0; + + public static void readUniqueNames(String fileName) { + try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { + String line; + while ((line = reader.readLine()) != null) { + uniqueNames.addAll(Arrays.asList(line.split(" "))); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static String getUniqueName() { + if (uniqueNames.isEmpty()) { + throw new RuntimeException("No unique names provided to NameDistibutor"); + } + + String name = uniqueNames.get(currUniqueNameIndex); + currUniqueNameIndex = (currUniqueNameIndex + 1) % uniqueNames.size(); + return name; + } + + public static String getCounterName(int counter) { + StringBuilder nameBuilder = new StringBuilder(); + do { + char letter = ALPHABET.charAt((int) (counter % ALPHABET.length())); + nameBuilder.insert(0, letter); + counter /= ALPHABET.length(); + } while (counter > 0); + return nameBuilder.toString(); + } +} diff --git a/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/State.java b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/State.java new file mode 100644 index 0000000..a1ffe51 --- /dev/null +++ b/lab-02/src/by/waitingsolong/docks_and_hobos/helpers/State.java @@ -0,0 +1,10 @@ +package by.waitingsolong.docks_and_hobos.helpers; + +public class State { + public boolean hunger; + public boolean dead; + public State() { + this.dead = false; + this.hunger = false; + } +}