I am running multiple thread and Handler in my code.
And this is my Handler
PrizeRunnable mTempPotionRunnable = new PrizeRunnable(aaa);
handler.postDelayed(mTempPotionRunnable, 4000);
and
class PrizeRunnable implements Runnable {
String type;
PrizeRunnable(String type) {
this.type = type;
}
public void run() {
synchronized (this) {
if(!mIsHandlerStarted){
if(type.equals(aaa))
// Do something
else if(type.equals(bbb))
// Do something
mIsHandlerStarted = true;
handler.removeCallbacks(this);
}
}
}
}
But sometime it run simultaneously.
i don not know the reason.
UPDATED
I try to change it to:
handler.postDelayed(mTempPotionRunnable, 4000);
and
Runnable mTempPotionRunnable = new Runnable() {
#Override
public void run() {
synchronized (this) {
if(!mIsHandlerStarted){
// Do something
mIsHandlerStarted = true;
handler.removeCallbacks(mMetalRunnable);
}
}
}
};
May be it resolve my problems. I am testing this method.
But i can't pass parameter to my Runnable . How can i do it?
My guess is that it's because you're synchronizing on the current instance:
synchronized (this) {
...
}
so unless you pass the same instance to all the handlers each one will use a different lock object. Try a static lock instead:
class PrizeRunnable implements Runnable {
String type;
private static final Object lock = new Object();
PrizeRunnable(String type) {
this.type = type;
}
public void run() {
synchronized (lock) {
if(!mIsHandlerStarted){
if(type.equals(aaa))
// Do something
else if(type.equals(bbb))
// Do something
mIsHandlerStarted = true;
handler.removeCallbacks(this);
}
}
}
}
Make global variable and i can pass parameter to my Runnable
Related
I have 2 threads, one calls get() method, another put() method.
I need to synchronize this methods in order to see result of get only after put. I do know how to do this other way, but I want to understand why am i getting .IllegalMonitorStateException with this code.
public class TransferObject {
private int value;
protected volatile boolean isValuePresent = false; //use this variable
public synchronized int get() {
synchronized (TransferObject.class) {
System.out.println("Got: " + value);
notify();
}
return value;
}
public void put(int value) {
synchronized (TransferObject.class) {
this.value = value;
System.out.println("Put: " + value);
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Here is example of 2 threads.
public class ConsumerTask implements Runnable {
private TransferObject transferObject;
protected volatile boolean stopped;
public ConsumerTask(TransferObject transferObject) {
this.transferObject = transferObject;
new Thread(this, "ConsumerTask").start();
}
public void run() {
while (!stopped) {
transferObject.get();
}
}
public void stop() {
stopped = true;
}
}
public class ProducerTask implements Runnable {
private TransferObject transferObject;
protected volatile boolean stopped;
static volatile AtomicInteger i = new AtomicInteger(0);
public ProducerTask(TransferObject transferObject) {
this.transferObject = transferObject;
new Thread(this, "ProducerTask").start();
}
public void run() {
while (!stopped) {
transferObject.put(i.incrementAndGet());
}
}
public void stop() {
stopped = true;
}
}
You have two threads and one object for locking TransferObject.class.
When your thread ConsumerTask gets the lock, object TransferObject.class don't have sleeping threads, and when you call notify() for this monitor you get IllegalMonitorStateException
From the description for method notify:
Wakes up a single thread that is waiting on this object's monitor.
You don't have waiting treads for monitor TransferObject.class
This is a pseudocode version of my current working code:
public class DataTransformer {
private final boolean async = true;
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
public void modifyAsync(Data data) {
if (async) {
executorService.submit(new Runnable() {
#Override
public void run() {
modify(data);
}
});
} else {
modify(data);
}
}
// This should actually be a variable inside modify(byte[] data)
// But I reuse it to avoid reallocation
// This is no problem in this case
// Because whether or not async is true, only one thread is used
private final byte[] temp = new byte[1024];
private void modify(Data data) {
// Do work using temp
data.setReady(true); // Sets a volatile flag
}
}
Please read the comments. But now I want to use Executors.newFixedThreadPool(10) instead of Executors.newSingleThreadExecutor(). This is easily possible in my case by moving the field temp inside modify(Data data), such that each execution has it's own temp array. But that's not what I want to do because i want to reuse the array if possible. Instead I want for each of the 10 threads a temp array. What's the best way to achieve this?
As static variable is shared between all Threads, so you could declare as static. But if you want to use different values then either use Threadlocal or use different object.
With ThreadLocal you could do :
ThreadLocal<byte[]> value = ThreadLocal.withInitial(() -> new byte[1024]);
You could also use object like this:
public class Test {
public static void main(String[] args) {
try {
Test test = new Test();
test.test();
} catch (Exception e) {
e.printStackTrace();
}
}
class Control {
public volatile byte[] temp = "Hello World".getBytes();
}
final Control control = new Control();
class T1 implements Runnable {
#Override
public void run() {
String a = Arrays.toString(control.temp);
System.out.println(a);
}
}
class T2 implements Runnable {
#Override
public void run() {
String a = Arrays.toString(control.temp);
System.out.println(a);
}
}
private void test() {
T1 t1 = new T1();
T2 t2 = new T2();
new Thread(t1).start();
new Thread(t2).start();
}
}
EDIT:
Edited the question in response to #maress answer below.
I have a web service in java (async enabled), which when called performs a call to another service asynchronously. In my Controller I have this:
private boolean receivedEvent = false;
private final Object SYNC = new Object();
public Callable<String> doStuff()
{
callSomeAsyncFunction();
return new Callable<String> ()
{
#Override
public String call() throws Exception {
synchronized (SYNC)
{
while (receivedEvent == false)
{
SYNC.wait();
}
receivedEvent = false;
System.out.println("RETURN");
return "ok";
}
}
};
}
public void onMyEvent(MyEvent event)
{
synchronized (SYNC)
{
receivedEvent = true;
System.out.println("RECEIVED");
SYNC.notify();
}
}
EDIT: The notification never gets through. System.out.println("RETURN") is never called. The events are being received ('RECEIVED' is shown).
Now all I want to do is wait for the callSomeAsyncFunction() to finish executing. When done, it triggers an event on the handler public void onMyEvent(MyEvent event).
Any suggestions? I am not even sure if my approach makes sense at all.
Synchronize always on a final instance.
private MyEvent myEvent;
private final Object SYNC = new Object();
public Callable<String> doStuff()
{
callSomeAsyncFunction();
return new Callable<String> ()
{
#Override
public String call() throws Exception {
synchronized (SYNC)
{
while (myEvent == null)
{
SYNC.wait();
}
return "ok";
}
}
};
}
public void onMyEvent(MyEvent event)
{
synchronized (SYNC)
{
myEvent = event;
SYNC.notifyAll();
}
}
Ok, so, I have a java class in which every method must run in a thread.
only one thread is executed per time and at a specific time.
I've implemented like this, with a inner class that extends Thread.
private class MyOperation extends Thread {
public static final String M1 = "method1";
public static final String M2 = "method2";
public static final String M3 = "method3";
protected long scheduledStartTime = 0;
private String type;
public MyOperation(String type, long milliSecondsToWait) {
this.type = type;
scheduledStartTime = System.currentTimeMillis() + mlliSecondsToWait;
}
#Override
public void run() {
switch(type){
case M1:
doMethod1();
break;
case M2:
doMethod3();
break;
case M3:
doMethod3();
break;
}
setCurrentOperation(null);
}
}
private void setCurrentOperation(MyOperation task) {
synchronized (currentOperation) {
this.currentOperation = task;
}
}
then I have the Thread queue and the current running thread
private MyOperation currentOperation;
private Queue <MyOperation> operationList;
And I'm fetching tasks like this:
private void fetchTasks() {
new Thread() {
#Override
public void run() {
while(true) {
if(currentOperation == null && !operationList.isEmpty()) {
currentOperation = getOperation();
while(currentOperation.scheduledStartTime > System.currentTimeMillis()) {
// do nothing, wait for proper time;
}
currentOperation.start();
}
}
}
}.start();
}
private MyOperation getOperation() {
synchronized (operationList) {
return operationList.remove();
}
}
and I'm adding thread to the queue like this, for example:
addOperation(new MyOperation(M1, 5));
private void addOperation(MyOperation task) {
synchronized (operationList) {
operationList.add(task);
}
}
My questions are:
Is there a better way to run each method in a diffent thread?
Is this way of fetching the threads queue correct?
Thank you very much
Just a little thing: if your operationsList is empty or the currentOperation is not null your thread starts going in circles really fast.
You could use Thread.wait() and .notify() to avoid this.
Also you are using currentOperation with and without synchronized. This could get you into trouble.
Have you condsidered using a ScheduledExecutorService (java.util.concurrent) to schedule your tasks?
I am attempting to pass the return value from scheduling a task into an anonymous class, but I am running into trouble. If I set the return value to a final variable, it says it is not initialized:
/* Not initialized */
final BukkitTask task = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
public void run() {
/* irrelevant code */
task.cancel();
}
}, 0L, 20L);
I have also attempted passing a variable by calling a method within the anonymous class, however it changes the return type to void and therefore I cannot pass a proper value:
BukkitTask temp = null;
/* Returns void */
temp = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
private BukkitTask task;
public void initTask(BukkitTask task) {
this.task = task;
}
public void run() {
/* irrelevant code */
task.cancel();
}
}.initTask(temp), 0L, 20L);
How can I pass a returned value into an anonymous class within the code?
You can define this class
class Box<T> {
public volatile T value;
}
and use it like this:
final Box<BukkitTask> taskBox = new Box<BukkitTask>();
taskBox.value = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
public void run() {
/* irrelevant code */
taskBox.value.cancel();
}
}, 0L, 20L);
However, taskBox.value in run could still be null depending on when runTaskTimer actually executes the runnable.
My idea, which might sound stupid, would be to create a global variable to which you assign the return value. Then, have a static method that would return this value to you in the anonymous class.
I seem to have figured out an answer rather quickly!
You can change the return type of the init method, and then it will return the proper values for the code!:
BukkitTask task = null;
task = Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
private BukkitTask task;
public Runnable initTask(BukkitTask task) {
this.task = task;
return this;
}
public void run() {
/* irrelevant code */
task.cancel();
}
}.initTask(task), 0L, 20L);
I am not sure what are you trying to do. Would Callable instead of Runnable solve the problem? http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html
see this example
public static void main(String[] args) {
final Object objectA[] = new String[1];
new Thread(new Runnable() {
private A refA = null;
public void run() {
objectA[0] = "Hello World or your object";
}
}).start();;
while (objectA[0] == null){
}
System.out.println(objectA[0]);
}