I have waitandsweep method in which I create a runnable task and schedule it using threadpoolexecutor. From runnable task I am calling external method isSliceDone() eventhough the value is true, it is not honouring it. meaning the control is going to next else if part. I think there is some synchronization issue here. Can someone help pls ?
protected void waitAndSweep(final String symbol) {
try {
runnable = new Runnable() {
#Override
public void run() {
try {
if (isSliceDone()) {
long timeSinceLastSliceQtySent = lastSliceSentTime == 0 ? getInterval() : System.currentTimeMillis() - lastSliceSentTime;
long waitTime = timeSinceLastSliceQtySent >= getInterval() ? 0 : getInterval() - timeSinceLastSliceQtySent;
if (waitTime > 0) {
logTradeEvent("waitAndSweep", symbol, "waittime: " + waitTime);
Thread.sleep(waitTime);
}
} else if (sweepInterval > 0) {
// It always comes here eventhough isSliceDone is true.
logTradeEvent("waitAndSweep", symbol, "sweepInterval: " + sweepInterval);
Thread.sleep(sweepInterval);
}
callSweep(symbol);
} catch (Exception e) {
}
}
};
Future<?> self = threadPoolExecutor.submit(runnable);
} catch (Exception e) {
}
}
private boolean isSliceDone() {
synchronized (this) {
double sliceQuantity = getSliceQuantity();
if (Quant.equals(sentSliceQty % sliceQuantity, 0.0) && Quant.equals(executedSliceQty % sliceQuantity, 0.0)) {
return Quant.greater(sentSliceQty, executedSliceQty) ? false : true;
}
return false;
}
}
Related
Actually I make an update through Bluetooth. In first time I erase the memory bank and then I write an hexa File on it.
But half the time an update will don't work correctly, for every data I transfer the first writeCharacteristic will return false.
It happen on an entire update half the time.
I try in debug mode but the method never return false in that case, of course it's probably a delay problem, but I can't increase the time.
This is my code for send my data :
public void sendTX(final byte[] sMessage) {
BluetoothGattService service = mBluetoothGatt.getService(UUID_SERVICE_SERIAL);
if (service != null && sMessage != null) {
Log.d(TAG,"sMessage : " + sMessage);
final BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID_TX);
if (characteristic != null) {
Thread thread = new Thread() {
public void run() {
if (sMessage.length > 20) {
for (int i = 0; i < sMessage.length; i += 20) {
byte[] byteArraySplit = Arrays.copyOfRange(sMessage, i, i + 20 < sMessage.length ? i + 20 : sMessage.length);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
characteristic.setValue(byteArraySplit);
while(!mBluetoothGatt.writeCharacteristic(characteristic)) {
try {
TimeUnit.MILLISECONDS.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} else {
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
characteristic.setValue(sMessage);
while(!mBluetoothGatt.writeCharacteristic(characteristic)){
try {
TimeUnit.MILLISECONDS.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
thread.start();
} else {
Log.d(TAG, "UUID TX null");
}
} else {
Log.d(TAG, "Service BLE null");
}
}
And this is the code of the native writeCharacteristic method :
public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
&& (characteristic.getProperties() &
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;
if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
BluetoothGattService service = characteristic.getService();
if (service == null) return false;
BluetoothDevice device = service.getDevice();
if (device == null) return false;
synchronized(mDeviceBusy) {
if (mDeviceBusy) return false;
mDeviceBusy = true;
}
try {
mService.writeCharacteristic(mClientIf, device.getAddress(),
characteristic.getInstanceId(), characteristic.getWriteType(),
AUTHENTICATION_NONE, characteristic.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
return false;
}
return true;
}
Never use timeouts to try to workaround this issue. The proper way is to wait for the callback and then perform the next request. See Android BLE BluetoothGatt.writeDescriptor() return sometimes false.
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.");
}
I have a serial connection which shall only be used by a single thread. But before I submit a new Task to the executors I want check if that certain Task is already in the queu(e.g for polling values).
executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
TaskRunnable runn = new TaskRunnable(
Integer.toString(i), "42");
if (!executor.getQueue().contains(runn)) {
executor.submit(runn);
}
}
}
}
}).start();
public void write(String addr, String value) {
// write
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
class TaskRunnable implements Runnable {
String addr, value;
public TaskRunnable(String addr, String value) {
this.addr = addr;
this.value = value;
}
#Override
public void run() {
write(addr, value);
System.out.println("Executed: " + addr + " - "
+ executor.getQueue().size());
}
#Override
public boolean equals(Object obj) {
TaskRunnable other = (TaskRunnable) obj;
return this.addr.equals(other.addr);
}
#Override
public int hashCode() {
int hash = 7;
hash = 17 * hash + (this.addr != null ? this.addr.hashCode() : 0);
return hash;
}
}
If I check executor.getQueue() the type is BlockingQueue<Runnable> but if I do executor.getQueue().contains(task) the equals method of TaskRunnable is called with an object of type FutureTask and I get this exception
java.util.concurrent.FutureTask cannot be cast to ExecutorTest$TaskRunnable
Any Idea how I can check If a certain TaskRunnable is already in the queue?
You need to store the Future returned from executor.submit(runn);. You can then ask if the queue contains the Future.
Replace the executor.submit(Runnable) to executor.execute(Runnable); it should then not repack your Runnable into it's own task.
I am still a java newbie and trying to play around learning threads. My question is that it does not loop 5 times. It runs one time and exits. I am using a.class to lock on the class object, such that both the threads are locking on the same object monitor.
class a implements Runnable {
Thread thr;
int count;
String time;
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tick";
System.out.println(time);
notify();
while (time == "Tock") {
wait();
}
}
} catch (Exception e) {
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tock";
System.out.println(time);
notify();
while (time == "Tick") {
wait();
}
}
} catch (Exception e) {
}
}
}
}
}
public class b {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
Here you go, with the original code:
class a implements Runnable {
Thread thr;
int count;
static String time = "Tock";
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
while (time.equals("Tock")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tock";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
while (time.equals("Tick")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tick";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
The problem was that you were calling wait and notify on the implicit this object, when the lock was being held on the a.class object, hence you must call wait/notify on a.class. That was it.
I also did a small restructuring, since I assume you wanted them to print Tick and Tock in an alternating sequence, right?
The answer to why you only loop once is that you call notify() on an object that is not locked and thus an IllegalMonitorStateException is thrown and caught by the empty catch statement.
This is one way to do it. Not saying that it is the best. I tried to keep it close to your code:
public class TickTock {
static final int N = 4;
Object lock = new Object();
int token;
class Worker extends Thread {
int id;
Worker(int id) {
this.id = id;
}
#Override
public void run() {
try {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
while (id != token%N) lock.wait();
System.out.println(id + " " + i);
token++;
lock.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void start() {
for (int i = 0; i < N; i++) {
new Worker(i).start();
}
}
public static void main(String[] args) {
new TickTock().start();
}
}
When comparing strings (and objects in general), you should use equals as opposed to == (which is generally reserved for primitives): while(time.equals("Tock")). == on strings will often times result in false when you want it to (and think it should) return true, and hence your loop will exit before expected.
I'm trying to simulate a simple thermostat, using multi-threading. The thermostat should increase the temperature in order to reach the value that the user requested for which is "Max" value in the code below. I have two thread, one in charge of increasing the temperature and the other for decreasing it. but the condition for decreasing is it should be only running when the gas is off.
but I have a problem with implementing this concept. as the code below runs, the second thread keeps throwing exception of null!
<pre><code>`private void formWindowActivated(java.awt.event.WindowEvent evt) {
systemInitial();
Thread temperatureUp = new Thread()
{
#Override
public void run()
{
while(true)
{
Max = Integer.parseInt(lblDesiredTemp.getText());
Current = Integer.parseInt(lblCurrentTemp.getText());
try
{
if(Max>Current)
{
lblGasStatus.setText("On");
lblTemperatureSensor.setText("increasing");
increaseTemeture();
}
else
{
lblGasStatus.setText("Off");
if(Current != 0)
lblTemperatureSensor.setText("decreasing");
else
lblTemperatureSensor.setText("----");
}
}
catch(Exception ex)
{
txtLog.setText(ex.getMessage() + "\n" + txtLog.getText() );
}
}
}
};
Thread systemUpdater = new Thread()
{
#Override
public void run()
{
while(true)
{
try
{
notifyGasBoiler(this);
if(Current>0)
decreaseTemeture();
}
catch(Exception ex)
{
txtLog.setText(ex.getMessage() + "\n" + txtLog.getText() );
}
}
}
};
temperatureUp.start();
systemUpdater.start();
}
private synchronized void notifyGasBoiler(Thread gasOff) throws InterruptedException
{
try
{
if("On".equals(lblGasStatus.getText()))
{
gasOff.wait();
txtLog.setText(txtLog.getText() + "\n" + gasOff.getName() + " waits.");
}
else
notifyAll();
}
catch (Exception ex)
{
txtLog.setText(ex.getMessage() + "\n" + txtLog.getText() );
}
}`
what am I missing here?
UPDATE I:
this is the log I'm getting by running the system and request the 2 temperature:
Temperature increased to 1
Temperature increased to 2
null
null
null
....
UPDATE II:
I used printStackTrace for exception and it got me this:
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at sol.smarthome.GUI.notifyGasBoiler(GUI.java:300)
at sol.smarthome.GUI.access$900(GUI.java:14)
at sol.smarthome.GUI$5.run(GUI.java:276)
Update III
<pre><code>`private void btnUpActionPerformed(java.awt.event.ActionEvent evt) {
if(Max<=8)
{
Max++;
String strI = String.valueOf(Max);
lblDesiredTemp.setText(strI);
setGasBoilerStatus();
}
}
private void btnDownActionPerformed(java.awt.event.ActionEvent evt) {
if(Max>0)
{
Max--;
String strI = String.valueOf(Max);
lblDesiredTemp.setText(strI);
setGasBoilerStatus();
}
}
private void formWindowActivated(java.awt.event.WindowEvent evt) {
systemInitial();
tempUp = new temperatureUp();
tempDown = new temperatureDown();
tempUp.start();
tempDown.start();
}
private synchronized void increaseTemeture() throws InterruptedException
{
synchronized (monitor) {
if (!getBoilerStatus())
{
tempUp.wait();
//return;
}
else
{
Max = Integer.parseInt(lblDesiredTemp.getText());
Current = Integer.parseInt(lblCurrentTemp.getText());
if(Max>Current)
{
lblGasStatus.setText("On");
lblTemperatureSensor.setText("increasing");
Thread.sleep(4000);
Current ++;
lblPumpStatus.setText("On");
lblCurrentTemp.setText(String.valueOf(Current));
txtLog.setText("Temperature increased to " + Current + "\n"+ txtLog.getText());
if(Current>8)
lblDanger.setVisible(true);
}
setGasBoilerStatus();
if(!isGasOn)
{
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
//Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
}
lblGasStatus.setText("Off");
if(Current != 0)
lblTemperatureSensor.setText("decreasing");
else
lblTemperatureSensor.setText("----");
}
}
}
}
private synchronized void decreaseTemeture() throws InterruptedException
{
synchronized (monitor) {
if(getBoilerStatus())
{
tempDown.wait();
//return;
}
else
{
Thread.sleep(4000);
if(Current == 0 )
return;
Current --;
lblCurrentTemp.setText(String.valueOf(Current));
lblDanger.setVisible(false);
txtLog.setText("Temperature decreased to " + Current + "\n"+ txtLog.getText());
if(Current<1)
lblPumpStatus.setText("Off");
else
lblPumpStatus.setText("On");
setGasBoilerStatus();
}
}
}
private void systemInitial()
{
lblDanger.setVisible(false);
isPilotOn.setSelected(true);
lblGasStatus.setText("Off");
lblPumpStatus.setText("Off");
isDone = true;
isGasOn = false;
Max = Current = 0;
}
// indicates if the boiler is on (true) or off (false)
// set as volatile to stop caching
private volatile boolean isBoilerOn = false;
protected int Max, Current;
protected boolean isDone, isGasOn, isPumpOn;
private temperatureUp tempUp;
private temperatureDown tempDown;
// Used to synchronize thread access to internal state (Current and
// isBoilerOn member variables. The monitor is private in order
// for this class to encapsulate its synchronization policy.
private final Object monitor = new Object();
// update the bolier's status to on (true) or off (false)
public void setBoilerSatus(boolean status) {
synchronized (monitor) {
// block threads until boiler is switched on
this.isBoilerOn = status;
// (see below), this is the place to notify them...
notifyAll();
}
}
// returns true if the boiler is on, false otherwise
public synchronized boolean getBoilerStatus() {
synchronized (monitor) {
return this.isBoilerOn;
}
}
private void setGasBoilerStatus() {
synchronized (monitor) {
if(Max>Current)
setBoilerSatus(true);
else
setBoilerSatus(false);
}
}
class temperatureUp extends Thread
{
#Override
public void run()
{
while(true)
{
try
{
increaseTemeture();
}
catch(Exception ex)
{
StringWriter w = new StringWriter();
ex.printStackTrace(new PrintWriter(w));
//txtLog.setText(w + "\n" + txtLog.getText());
}
}
}
};
class temperatureDown extends Thread
{
#Override
public void run()
{
while(true)
{
try
{
decreaseTemeture();
}
catch(Exception ex)
{
StringWriter w = new StringWriter();
ex.printStackTrace(new PrintWriter(w));
//txtLog.setText(w + "\n" + txtLog.getText());
}
}
}
};
`
Try creating a class Thermostat that encapsulate's your thermostat's state and behaviors. The trick is to use proper synchronization in order to maintain your program's invariants. Below you may find a sample implementation of a Thermostat class based on your requirements description, for illustration purposes. Notice how synchronization is used in order to preserve your invariants. Any method (such as up(int) and down(int) which both affect the current temperature) may be invoked concurrently by different threads, without race events or related hazards due to synchronization.
Again, this is for illustration purposes only:
public final class Thermostat {
// constant for maximum allowable temperature
public static final int MAX_TEMP = 100;
// the thermostat's current temperature
private int temp = 0;
// indicates if the boiler is on (true) or off (false)
private boolean boilerStatus = false;
public Thermostat() {
}
// Used to synchronize thread access to internal state (temp and
// boilerStatus member variables. The monitor is private in order
// for this class to encapsulate its synchronization policy.
private final Object monitor = new Object();
// update the bolier's status to on (true) or off (false)
public void setBoilerOn(boolean status) {
synchronized (monitor) {
this.boilerStatus = status;
// if you block threads until boiler is switched on
// (see below), this is the place to notify them...
}
}
// returns true if the boiler is on, false otherwise
public boolean isBoilerOn() {
synchronized (monitor) {
return this.boilerStatus;
}
}
// increase the thermostat's temperature by the specified units
// provided that the boiler has been set on
public void up(int units) {
synchronized (monitor) {
// don't increase the temperature if the boiler
// is not turned on...
if (!isBoilerOn()) {
// you could alternatively wait here if your
// thread needs to block...
return;
}
// increase the temperature
if ((temp + units) <= MAX_TEMP) {
temp += units;
} else {
// TODO : handle incorect user input here...
}
}
}
// decrease the thermostat's temperature by the specified units
// (negative values allowed)
public void down(int units) {
synchronized (monitor) {
temp -= units;
}
}
}
Try using the Full class name (dot) this
eg:
notifyGasBoiler(MyTempClass.this);