-
Notifications
You must be signed in to change notification settings - Fork 5
/
GenericPrinter.java
executable file
·150 lines (125 loc) · 3.05 KB
/
GenericPrinter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.vee.algorithms.concurrency;
import java.util.ArrayList;
import java.util.List;
public class GenericPrinter implements IPrinter{
List<String> buffer;
private int bufferSize = 20;
private final Thread dispatcher;
boolean blocking = false;
boolean closed = true;
GenericPrinter() {
buffer = new ArrayList<String>(bufferSize);
dispatcher = new Thread(new Dispatcher(this,buffer));
dispatcher.setDaemon(true);
dispatcher.setName("AsynGenericPrinter-"+dispatcher.getId());
dispatcher.start();
}
public void print(String str) {
synchronized (buffer) {
while(true) {
int prevSize = buffer.size();
if(prevSize < bufferSize) {
buffer.add(str);
/* if buffer had been empty
signal all threads waiting on buffer
to check their conditions.
ie a new event is added to process*/
if(prevSize == 0) {
buffer.notifyAll();
}
break;
}
}
// Following code is only reachable if buffer is full
/*
* if blocking then wait for a buffer notification
* FIXME Check Thread interrupt and isDispatcher
*/
if(blocking) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class Dispatcher implements Runnable {
IPrinter parentPrinter;
List<String> buffer;
Dispatcher(IPrinter p,List<String> buffer) {
parentPrinter = p;
this.buffer = buffer;
}
public void run() {
try {
while(true) {
String[] events = null;
synchronized (buffer) {
int bufferSize = buffer.size();
while(bufferSize == 0) {
//Wait till buffer has an event
/* If you don't add a buffer notifyall after
* processing of events, then buffer will
* perpetually wait for new events
*/
buffer.wait();
//buffer has a event, continue processing
bufferSize = buffer.size();
}
if(bufferSize > 0) {
//FIXME track discarded events
events = new String[bufferSize];
//Add the events from buffer to array
buffer.toArray(events);
//FIXME add discarded events to end of array
//Clear Buffer
buffer.clear();
//Allow blocked events continue
/*
* If not, any thread waiting on this buffer will
* not close even the current thread (see buffer.wait)
*/
buffer.notifyAll();
}
}
//process events
for(String event : events) {
process(event);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void process(String str) {
System.out.println(str);
fib(Integer.parseInt(str.split("-")[1]));
}
public int fib(int n) {
if(n<=1) {
return n;
}
else{
return fib(n-1)+fib(n-2);
}
}
}
public void close() {
//FIXME Do we need to have a closed flag
synchronized (buffer) {
buffer.notifyAll();
}
try {
dispatcher.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void finalize() {
close();
}
//FIXME setBufferSize
public void setBufferSize() {
}
}