Skip to content

Commit 8ef9ea9

Browse files
committed
Complete lab4
1 parent 4f4d0ec commit 8ef9ea9

File tree

10 files changed

+657
-45
lines changed

10 files changed

+657
-45
lines changed

src/dp/lab4/a/Database.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package dp.lab4.a;
2+
3+
import java.io.IOException;
4+
import java.util.ArrayList;
5+
import java.util.Arrays;
6+
import java.util.List;
7+
8+
public class Database {
9+
public static void main(String[] args) throws IOException, InterruptedException {
10+
FileInteractor interactor = new FileInteractor("WritersDatabase.bin");
11+
interactor.clearFile();
12+
13+
Thread managerThread = new Thread(() -> {
14+
List<String> names = new ArrayList<>(
15+
Arrays.asList("Vasya", "Petya", "Vova", "Grysha",
16+
"Semen", "Fedor", "Ivan", "Alexandr"));
17+
18+
List<String> phones = new ArrayList<>(
19+
Arrays.asList("380504440000", "380504441111", "380505550000", "380505551111", "380501234567",
20+
"380509871890", "380090123455", "380965858444"));
21+
22+
for (int i = 0, n = names.size(); i < n; i++) {
23+
interactor.writeToFile(new Writer(names.get(i), phones.get(i)));
24+
}
25+
26+
interactor.removeByKey("Fedor", FileInteractor.Field.NAME);
27+
interactor.removeByKey("Semen", FileInteractor.Field.NAME);
28+
interactor.removeByKey("Vova", FileInteractor.Field.NAME);
29+
interactor.removeByKey("380504441111", FileInteractor.Field.PHONE);
30+
interactor.writeToFile(new Writer("Anton", "45684968896846"));
31+
interactor.removeByKey("380965858444", FileInteractor.Field.PHONE);
32+
interactor.removeByKey("380090123455", FileInteractor.Field.PHONE);
33+
interactor.writeToFile(new Writer("Stepan", "5745754685468"));
34+
});
35+
managerThread.start();
36+
Thread.sleep(1);
37+
38+
Thread nameFinderThread = new Thread(() -> {
39+
List<String> names = new ArrayList<>(
40+
Arrays.asList("Vova", "Grysha", "Fedor", "Alexandr"));
41+
for (String currentName : names) {
42+
System.out.printf("By name %s: %s%n", currentName,
43+
interactor.findInFile(currentName, FileInteractor.Field.NAME));
44+
}
45+
});
46+
47+
Thread phoneFinderThread = new Thread(() -> {
48+
List<String> phones = new ArrayList<>(
49+
Arrays.asList("380504441111", "380504440000", "380509871890", "380090123455"));
50+
for (String currentPhone : phones) {
51+
System.out.printf("By phone %s: %s%n", currentPhone,
52+
interactor.findInFile(currentPhone, FileInteractor.Field.PHONE));
53+
}
54+
});
55+
56+
nameFinderThread.start();
57+
phoneFinderThread.start();
58+
}
59+
}

src/dp/lab4/a/FileInteractor.java

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package dp.lab4.a;
2+
3+
import java.io.*;
4+
import java.util.ArrayList;
5+
6+
public class FileInteractor {
7+
public enum Field {
8+
PHONE,
9+
NAME
10+
}
11+
12+
private String fileName;
13+
private ObjectOutputStream output;
14+
private final RWLock lock;
15+
16+
public FileInteractor(String fileName) {
17+
this.fileName = fileName;
18+
this.lock = new RWLock();
19+
20+
try {
21+
output = new ObjectOutputStream(new FileOutputStream(fileName, true));
22+
} catch (IOException e) {
23+
e.printStackTrace();
24+
}
25+
}
26+
27+
public void writeToFile(Writer writer) {
28+
try {
29+
lock.lockWrite();
30+
output.writeObject(writer);
31+
lock.unlockWrite();
32+
} catch (IOException | InterruptedException e) {
33+
e.printStackTrace();
34+
Thread.currentThread().interrupt();
35+
}
36+
}
37+
38+
public Writer findInFile(String key, Field field) {
39+
try {
40+
lock.lockRead();
41+
} catch (InterruptedException e) {
42+
e.printStackTrace();
43+
Thread.currentThread().interrupt();
44+
}
45+
46+
try (
47+
FileInputStream istream = new FileInputStream(fileName);
48+
ObjectInputStream input = new ObjectInputStream(istream)
49+
) {
50+
51+
boolean isFound = false;
52+
Writer answer = new Writer("", "");
53+
while (!isFound && istream.available() > 0) {
54+
Writer writer = (Writer) input.readObject();
55+
56+
if ((field == Field.NAME && writer.getName().equals(key)) ||
57+
(field == Field.PHONE && writer.getPhone().equals(key))) {
58+
answer = writer;
59+
isFound = true;
60+
}
61+
}
62+
lock.unlockRead();
63+
return answer;
64+
} catch (IOException | ClassNotFoundException e) {
65+
e.printStackTrace();
66+
}
67+
68+
return null;
69+
}
70+
71+
public void clearFile() throws IOException {
72+
PrintWriter writer = new PrintWriter(fileName);
73+
writer.print("");
74+
writer.close();
75+
output = new ObjectOutputStream(new FileOutputStream(fileName, true));
76+
}
77+
78+
private ArrayList<Writer> getAllItems(FileInputStream istream, ObjectInputStream input) throws IOException, ClassNotFoundException {
79+
ArrayList<Writer> array = new ArrayList<>();
80+
while (istream.available() > 0) {
81+
Writer buffer = (Writer) input.readObject();
82+
array.add(buffer);
83+
}
84+
return array;
85+
}
86+
87+
88+
public void removeByKey(String key, Field field) {
89+
try {
90+
lock.lockWrite();
91+
FileInputStream istream = new FileInputStream(fileName);
92+
ObjectInputStream input = new ObjectInputStream(istream);
93+
94+
ArrayList<Writer> array = getAllItems(istream, input);
95+
96+
int index = -1;
97+
if (field == Field.NAME) {
98+
for (int i = 0; i < array.size(); ++i) {
99+
if (array.get(i).getName().equals(key)) {
100+
index = i;
101+
break;
102+
}
103+
}
104+
} else if (field == Field.PHONE) {
105+
for (int i = 0; i < array.size(); ++i) {
106+
if (array.get(i).getPhone().equals(key)) {
107+
index = i;
108+
break;
109+
}
110+
}
111+
}
112+
113+
if (index == -1) {
114+
lock.unlockWrite();
115+
return;
116+
}
117+
array.remove(index);
118+
119+
clearFile();
120+
121+
for (Writer item : array) {
122+
output.writeObject(item);
123+
}
124+
lock.unlockWrite();
125+
} catch (IOException | InterruptedException | ClassNotFoundException e) {
126+
e.printStackTrace();
127+
Thread.currentThread().interrupt();
128+
}
129+
}
130+
131+
public void printFile() throws IOException, ClassNotFoundException, InterruptedException {
132+
lock.lockRead();
133+
FileInputStream istream = new FileInputStream(fileName);
134+
ObjectInputStream input = new ObjectInputStream(istream);
135+
136+
while (istream.available() > 0) {
137+
Writer buffer = (Writer) input.readObject();
138+
System.out.println(buffer);
139+
}
140+
lock.unlockRead();
141+
}
142+
}

src/dp/lab4/a/RWLock.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package dp.lab4.a;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
public class RWLock {
7+
private final Map<Thread, Integer> readingThreads =
8+
new HashMap<>();
9+
10+
private int writeAccesses = 0;
11+
private int writeRequests = 0;
12+
private Thread writingThread = null;
13+
14+
public synchronized void lockRead() throws InterruptedException {
15+
Thread callingThread = Thread.currentThread();
16+
while (!canGrantReadAccess(callingThread)) {
17+
wait();
18+
}
19+
20+
readingThreads.put(callingThread,
21+
(getReadAccessCount(callingThread) + 1));
22+
}
23+
24+
private boolean canGrantReadAccess(Thread callingThread) {
25+
if (isWriter(callingThread)) return true;
26+
if (hasWriter()) return false;
27+
if (isReader(callingThread)) return true;
28+
return !hasWriteRequests();
29+
}
30+
31+
32+
public synchronized void unlockRead() {
33+
Thread callingThread = Thread.currentThread();
34+
if (!isReader(callingThread)) {
35+
throw new IllegalMonitorStateException("Calling Thread does not" +
36+
" hold a read lock on this ReadWriteLock");
37+
}
38+
int accessCount = getReadAccessCount(callingThread);
39+
if (accessCount == 1) {
40+
readingThreads.remove(callingThread);
41+
} else {
42+
readingThreads.put(callingThread, (accessCount - 1));
43+
}
44+
notifyAll();
45+
}
46+
47+
public synchronized void lockWrite() throws InterruptedException {
48+
writeRequests++;
49+
Thread callingThread = Thread.currentThread();
50+
while (!canGrantWriteAccess(callingThread)) {
51+
wait();
52+
}
53+
writeRequests--;
54+
writeAccesses++;
55+
writingThread = callingThread;
56+
}
57+
58+
public synchronized void unlockWrite() {
59+
if (!isWriter(Thread.currentThread())) {
60+
throw new IllegalMonitorStateException("Calling Thread does not" +
61+
" hold the write lock on this ReadWriteLock");
62+
}
63+
writeAccesses--;
64+
if (writeAccesses == 0) {
65+
writingThread = null;
66+
}
67+
notifyAll();
68+
}
69+
70+
private boolean canGrantWriteAccess(Thread callingThread) {
71+
if (isOnlyReader(callingThread)) return true;
72+
if (hasReaders()) return false;
73+
if (writingThread == null) return true;
74+
return isWriter(callingThread);
75+
}
76+
77+
78+
private int getReadAccessCount(Thread callingThread) {
79+
Integer accessCount = readingThreads.get(callingThread);
80+
if (accessCount == null) return 0;
81+
return accessCount;
82+
}
83+
84+
private boolean hasReaders() {
85+
return readingThreads.size() > 0;
86+
}
87+
88+
private boolean isReader(Thread callingThread) {
89+
return readingThreads.get(callingThread) != null;
90+
}
91+
92+
private boolean isOnlyReader(Thread callingThread) {
93+
return readingThreads.size() == 1 &&
94+
readingThreads.get(callingThread) != null;
95+
}
96+
97+
private boolean hasWriter() {
98+
return writingThread != null;
99+
}
100+
101+
private boolean isWriter(Thread callingThread) {
102+
return writingThread == callingThread;
103+
}
104+
105+
private boolean hasWriteRequests() {
106+
return this.writeRequests > 0;
107+
}
108+
}

src/dp/lab4/a/Writer.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package dp.lab4.a;
2+
3+
import java.io.Serializable;
4+
import java.util.StringJoiner;
5+
6+
public record Writer(String name, String phone) implements Serializable {
7+
8+
public String getName() {
9+
return name;
10+
}
11+
12+
public String getPhone() {
13+
return phone;
14+
}
15+
16+
@Override
17+
public String toString() {
18+
return new StringJoiner(", ", Writer.class.getSimpleName() + " [", "]")
19+
.add(name)
20+
.add(phone)
21+
.toString();
22+
}
23+
}

0 commit comments

Comments
 (0)