I have this code that is executed when a file is modified
public class WatchQueueReaderTask<Void> extends Task {
...
protected Object call() throws Exception {
try {
// get the first event before looping
WatchKey key = myWatcher.take();
while (key != null) {
// we have a polled event, now we traverse it and
// receive all the states from it
for (WatchEvent event : key.pollEvents()) {
WatchEvent.Kind eventType = event.kind();
if (eventType == OVERFLOW) {
continue;
}
process(event);
if (isCancelled()) {
System.out.println("WatchQueueReaderTask::call isCancelled");
return null;
}
}
key.reset();
key = myWatcher.take();
}
} catch (InterruptedException e) {
ArrayList<WatchFileItem> auxList = threadFileToWatch;
for (WatchFileItem obj : auxList) {
if (obj.file != null) {
try {
obj.file.close();
} catch (IOException ex) {
System.out.println("errore in file close");
Logger.getLogger(WatchQueueReaderTask.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//e.printStackTrace();
}
System.out.println("Stopping thread");
return null;
}
...
private synchronized void process(WatchEvent evt) {
... }
}
I call it using:
ThreadFactory processingThreadFactoryForRealtime = null;
ExecutorService processingThreadFactoryForRealtimeExecutor = null;
WatchQueueReaderTask mywatchQueueReader = null;
processingThreadFactoryForRealtime = new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("FileWatcherTask");
t.setDaemon(true);
return t;
}
};
processingThreadFactoryForRealtimeExecutor = Executors.newSingleThreadExecutor(processingThreadFactoryForRealtime);
mywatchQueueReader = new WatchQueueReaderTask(realtimePath, watcherServiceForRealtime, fileToWatchForRealtime);
processingThreadFactoryForRealtimeExecutor.execute(mywatchQueueReader);
The problem is that execute simultaneously multiple methods process() without waiting for the previous is completed.
Where am I wrong?
Related
public class SemActionPlace {
public SemMonitor StartConsumerProducer() {
SemMonitor monitor = new SemMonitor();
List<Thread> threads = new LinkedList<>();
Thread p1 = new Thread(new Producer(monitor), "P1");
p1.start();
Thread c1 = new Thread(new Consumer(monitor), "C-odd");
c1.start();
Thread c2 = new Thread(new Consumer(monitor), "C-even");
c2.start();
threads.add(p1);
threads.add(c1);
threads.add(c2);
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return monitor;
}
}
the code work just fine when I start thread through start() - join(), however, I failed to find mistake when I try to do the same through the executor service. It's important for me to save names of the threads and mutual monitor. Please, tell me how can I execute the threads through the executor service ?
The piece of code below doen't work properly. Where is mistake ?
public SemMonitor StartConsumerProducer() {
SemMonitor monitor = new SemMonitor();
Thread p1 = new Thread(new Producer(monitor), "P1");
Thread c1 = new Thread(new Consumer(monitor), "C-odd");
Thread c2 = new Thread(new Consumer(monitor), "C-even");
ThreadPoolExecutor service = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);
service.execute(p1);
service.execute(c1);
service.execute(c2);
System.out.println(service.getCompletedTaskCount());
System.out.println(service.getCompletedTaskCount());
return monitor;
}
I need one simple thing from the executor server is that I wanna that it works like simple start() - join() solution works ( first piece of code ) .
class Consumer implements Runnable {
private final SemMonitor monitor;
Consumer(SemMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
long t = System.currentTimeMillis();
long end = t + 1000;
while (System.currentTimeMillis() < end) {
consoleLog(monitor.activeThreadName,false);
if (/*monitor.semaphore.tryAcquire() && */monitor.activeThreadName.equals( Thread.currentThread().getName())) {
try {
consoleLog(String.valueOf(Thread.currentThread().getName() + " was notified "),monitor.enableLog);
monitor.semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
monitor.get(Thread.currentThread().getName());
}
try{
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer implements Runnable {
private SemMonitor monitor;
Producer(SemMonitor monitor) {
this.monitor = monitor;
}
#Override
public void run() {
String threadNameToWork;
Integer randNum;
long t = System.currentTimeMillis();
long end = t + 500;
while (System.currentTimeMillis() < end) {
if (monitor.semaphore.tryAcquire()) {
randNum = ((Number) (random() * 100)).intValue();
if (randNum % 2 == 0) {
threadNameToWork = "C-even";
} else {
threadNameToWork = "C-odd";
}
try {
monitor.putItem(randNum, Thread.currentThread().getName(), threadNameToWork);
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class Monitor {
private double currItem;
private boolean isConsumersShouldWaitProducer = true;
private boolean isConsuming = false;
private String threadNameToWork;
synchronized void putRandNumber(double producerOutput, String producerName, String threadNameToWork) {
if (isConsumersShouldWaitProducer) {
System.out.println("Consumers wait for new Production");
}
this.threadNameToWork = threadNameToWork;
currItem = producerOutput;
System.out.println("Producer " + producerName + " putRandNumber Item: " + currItem);
if (currItem > 3) {
notifyAll();
isConsumersShouldWaitProducer = false;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void consumeRandNumber(String threadName) {
if (isConsumersShouldWaitProducer) {
try {
this.wait();
} catch (InterruptedException e) {
System.out.println("Caught Interrupted Exception while waiting to consume currItem: " + e.getMessage());
}
}
if (isConsuming) {
try {
this.wait();
isConsuming = true;
} catch (InterruptedException e) {
System.out.println("Caught Interrupted Exception while waiting to consume currItem: " + e.getMessage());
}
}
switch (Thread.currentThread().getName()) {
/*switch (threadNameToWork) {*/
case "C-odd":
isConsuming = true;
if (currItem % 2 != 0 && threadNameToWork.equals(Thread.currentThread().getName())) {
consumeItems(threadName);
}
isConsuming = false;
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
case "C-even":
isConsuming = true;
if (currItem % 2 == 0 && threadNameToWork.equals(Thread.currentThread().getName())) {
consumeItems(threadName);
}
isConsuming = false;
notifyAll();
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
default:
break;
}
}
private synchronized void consumeItems(String threadName) {
isConsumersShouldWaitProducer = true;
String randNumType = "*odd/even*";
System.out.println("Consumer:" + threadName + " consumed " + randNumType + " Items = " + currItem);
notifyAll();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You want to do something with Thread name right? The thread name you created in using new Thread will not pass into ExecutorService, but this will
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("thread-%d").build()
Then
ExecutorService exec = Executors.newSingleThreadExecutor(namedThreadFactory);
Now you have thread with name as thread-1, thread-2
OR set thread name in your run() method
Thread.currentThread().setName(myName)
To make sure your thread is finished, add this before you return the monitor,
service.shutdown();
while (!service.awaitTermination(10, TimeUnit.SECONDS)) {
log.info("Awaiting completion of threads.");
}
The Future object is never able to obtain access to the synchronized block of code so it never finishes and never returns. There isn't anything accessing writeOut() besides the thread so I am not sure why it is block.
public class FileManager {
private void writeOut() throws BusinessException {
if(f.exists() && f.canWrite()) {
synchronized (this) {
try (FileWriter fileWriter = new FileWriter(f)) {
String endLine = "\n";
fileWriter.write("");
for (Entry entry : directory) {
fileWriter.append(entry.getLastName());
fileWriter.append(CSV_DELIMITER);
fileWriter.append(entry.getFirstName());
fileWriter.append(CSV_DELIMITER);
fileWriter.append(entry.getPhoneNumber());
fileWriter.append(CSV_DELIMITER);
fileWriter.append(entry.getAddress());
fileWriter.append(endLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
System.out.println(f.getAbsolutePath() + " doesn't exist or can't be written to");
}
}
public void addEntry(Entry entryModel, boolean notify) {
assert entryModel != null;
synchronized (this) {
AddEntryAction addAction = new AddEntryAction(entryModel, notify);
AddEntryActor actor = new AddEntryActor(addAction);
actor.execute();
deleteActor(actor);
}
}
Here is the method that is called by execute():
private void executeAsynchronously() {
Callable<String> asyncTask = () -> {
try {
ServiceFw.fileManager.writeBack();
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BusinessException e) {
notifyFailure();
}
return "write back operation";
};
future = executor.submit(asyncTask);
Runnable poll = () -> {
if(future!=null) {
notifySuccess();
} else {
notifyFailure();
}
};
poll.run();
}
I´m try to build a application which, by threads, are listening to directory for changes. Everything works fine, but there is a little bug. I´m very new to the whole threads-thing... So, this problem probably based on my ignorance...
The program can se all the changes in the picked directory, BUT, when the threads are running, i cant modify the files inside the directory... Those are locked in the process...
I will be very happy if someone perhaps can give me some tips in how i can solve this.
Thank you in advance
DirWatch
public class DirWatch implements Runnable{
Path dirPath;
private boolean run = true;
private boolean created = false;
private boolean modified = false;
private boolean compressed = false;
private boolean isJSON = false;
/**
*
* #param path
* #throws IOException
*/
public void setWatchPath(String path) throws IOException {
dirPath = Paths.get(path);
try {
Boolean isFolder = (Boolean) Files.getAttribute(dirPath, "basic:isDirectory", new LinkOption[]{NOFOLLOW_LINKS});
if (!isFolder) {
throw new IllegalArgumentException("Path: " + dirPath + " is not a folder");
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
System.out.println("Watching path: " + path);
}
public void setDirPathWatchRun(boolean run){
this.run = run;
}
public boolean isCreated() {
return created;
}
public void setCreated(boolean created) {
this.created = created;
}
public boolean isModified() {
return modified;
}
public void setModified(boolean modified) {
this.modified = modified;
}
public boolean isCompressed() {
return compressed;
}
public void setCompressed(boolean compressed) {
this.compressed = compressed;
}
public boolean isJSON() {
return isJSON;
}
public void setJSON(boolean JSON) {
isJSON = JSON;
}
private void checkFileType(String fileName){
String extension = fileName.substring(fileName.length() - 4);
if(extension.equalsIgnoreCase(FILE_TYPE.TAR.getFileType())){
setCompressed(true);
System.out.println(extension);
}
if(extension.equalsIgnoreCase(".json")){
setJSON(true);
}
}
#Override
public void run() {
FileSystem fs = dirPath.getFileSystem ();
try(WatchService service = fs.newWatchService()) {
dirPath.register(service, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
WatchKey key = null;
while(run) {
key = service.take();
WatchEvent.Kind<?> kind = null;
for(WatchEvent<?> watchEvent : key.pollEvents()) {
kind = watchEvent.kind();
if (OVERFLOW == kind) {
System.out.println("OVERFLOW");
continue;
} else if (ENTRY_CREATE == kind) {
System.out.println("New path created: " + watchEvent.context().toString());
setCreated(true);
checkFileType(watchEvent.context().toString());
} else if (ENTRY_DELETE == kind){
System.out.println("Path deleted: " + watchEvent.context().toString());
setModified(true);
checkFileType(watchEvent.context().toString());
} else if (ENTRY_MODIFY == kind) {
System.out.println("Path modified: " + watchEvent.context().toString());
setModified(true);
checkFileType(watchEvent.context().toString());
}
}
if(!key.reset()) {
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Method Watch in another class
private void watch() throws IOException {
watchJSON = new DirWatch();
watchTAR = new DirWatch();
watchTAR.setWatchPath(serverArgs.getCompressedPath());
watchJSON.setWatchPath(serverArgs.getExtractedPath());
Runnable checkSourceActions = new Runnable() {
#Override
public void run() {
while(true) {
if (watchJSON.isCreated() || (watchJSON.isModified())) {
server();
}
if(watchTAR.isCreated() || (watchTAR.isModified())) {
extractFiles(fileHandler);
createManifest(fileHandler);
server();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread1 = new Thread(watchJSON);
Thread thread3 = new Thread(watchTAR);
Thread thread2 = new Thread(checkSourceActions);
thread1.start();
thread2.start();
thread3.start();
}
When I try to change the file while the program is running
I am using an actionListener to trigger an sequence of events and ultimatley this code is called:
public class ScriptManager {
public static Class currentScript;
private Object ScriptInstance;
public int State = 0;
// 0 = Not Running
// 1 = Running
// 2 = Paused
private Thread thread = new Thread() {
public void run() {
try {
currentScript.getMethod("run").invoke(ScriptInstance);
} catch(Exception e) {
e.printStackTrace();
}
}
};
public void runScript() {
try {
ScriptInstance = currentScript.newInstance();
new Thread(thread).start();
State = 1;
MainFrame.onPause();
} catch (Exception e) {
e.printStackTrace();
}
}
public void pauseScript() {
try {
thread.wait();
System.out.println("paused");
State = 2;
MainFrame.onPause();
} catch (Exception e) {
e.printStackTrace();
}
}
public void resumeScript() {
try {
thread.notify();
System.out.println("resumed");
State = 1;
MainFrame.onResume();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopScript() {
try {
thread.interrupt();
thread.join();
System.out.println("stopped");
State = 0;
MainFrame.onStop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The runnable is created and ran, however, the problem occurs when I try to use the any of the other methods, they lock my UI. (I'm assuming this is because im running this on the EDT) Does anyone know how to fix this?
That's not how you use wait and notify. They need to be executed on the thread that you are trying to pause and resume. Which means you need to send a message to the other thread somehow. There are various ways to do this, but the other thread needs to be listening for this message, or at least check for it occassionally.
Here I have two run methods which should synchronize each other.
Poller Class:
*/
public void run() {
int seqId = 0;
while(true) {
List<KpiMessage> list = null;
try{
if(!accumulator.isUsed){
try {
list = fullPoll(seqId);
if (!list.isEmpty()) {
seqId = list.get(0).getSequence();
accumulator.manageIngoing(list);
}
System.out.println("Updated");
wait();
} catch (Exception e1) {
e1.printStackTrace();
}
}
} catch (Exception e){
// TODO:
System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
/**
* Method which defines polling of the database and also count the number of Queries
* #param lastSeq
* #return pojo col
* #throws Exception
*/
public List<KpiMessage> fullPoll(int lastSeq) throws Exception {
Statement st = dbConnection.createStatement();
System.out.println("Polling");
ResultSet rs = st.executeQuery("Select * from msg_new_to_bde where ACTION = 814 and
STATUS = 200 order by SEQ DESC");
List<KpiMessage> pojoCol = new ArrayList<KpiMessage>();
try {
while (rs.next()) {
KpiMessage filedClass = convertRecordsetToPojo(rs);
pojoCol.add(filedClass);
}
for (KpiMessage pojoClass : pojoCol) {
System.out.print(" " + pojoClass.getSequence());
System.out.print(" " + pojoClass.getTableName());
System.out.print(" " + pojoClass.getAction());
System.out.print(" " + pojoClass.getKeyInfo1());
System.out.print(" " + pojoClass.getKeyInfo2());
System.out.print(" "+ pojoClass.getStatus());
System.out.println(" " + pojoClass.getEntryTime());
}
} finally {
try {
st.close();
rs.close();
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
Processing and Updating Class:
public void run() {
while(true){
try {
while(!accumulator.isUsed)
{
try {
System.out.println("Waiting for new outgoingmessages");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Collection<KpiMessage> outgoingQueue = generate(accumulator.outgoingQueue);
accumulator.manageOutgoing(outgoingQueue, dbConnection);
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
}
}
I have a logical error:
The poller is polling not only for new messsage but also reads the DB again and again from the first.
Also Updates again and again.
How to solve this synchronization problem.
Alternatively you could use a BlockingQueue to transfer the data between threads.
See BlockingQueue for details.
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final Queue<Integer> queue;
private int i = 0;
public Producer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i++);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final Queue<Integer> queue;
private int i = 0;
public Consumer(Queue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
Integer i = queue.poll();
if ( i != null ) {
ended = i == End;
System.out.println(i);
}
}
}
}
public void test() throws InterruptedException {
Queue queue = new LinkedBlockingQueue();
Producer p = new Producer(queue);
Consumer c = new Consumer(queue);
Thread pt = new Thread(p);
Thread ct = new Thread(c);
// Start it all going.
pt.start();
ct.start();
// Close it down
pt.join();
ct.join();
}
You should synchronize or rather hold the lock or monitor for the object that you are calling wait() or notify() on.
Here is what will help you : wait() throwing IllegalArgumentException
synchronized(lockObject){
lockObject.wait(); //you should hold the lock to be able to call wait()
}