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?
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am trying to design a thread pool at my end in java. As per my design I am using a java's Linkedlist DS inside a main runner thread class to hold on to all the submitted tasks. This task list is getting updated from the main class wherein the main class is adding a tasks to the task list. Inside my main runner thread I am running a while loop and constantly checking for whether the LinkedList is not empty , and if it contains a task then i am retrieving the task and executing it.
The problem here is that I have added a task from my main method in to the task list and I can see the size of this task list to be 1 from main method but inside the runner thread when i print the size of task list object , it shows it as 0.
Need help figuring out what exactly is happening here.
public class ReusableThread<T> extends Thread{
private volatile Queue<Work<T>> tasks = new LinkedList<Work<T>>();
private Work<T> currentWork;
private class Work<T>{
Result<T> result;
Taskable<T> task;
public Work(Result<T> result, Taskable<T> task) {
this.result = result;
this.task = task;
}
}
#Override
public void run() {
while(true){
//System.out.println("ReusableThread.run()");
System.out.println("Inside thread : " + getTasks().size()); //This print 0
if(!tasks.isEmpty()){
currentWork = getWork();
T value = currentWork.task.run();
//currentWork.result.setValue(currentWork.task.run());
}
//currentWork.result.setComplete(true);
}
}
public Work<T> getWork() {
return tasks.remove();
}
public Queue<Work<T>> getTasks() {
return tasks;
}
public Result<T> submit(Taskable<T> task) {
Result<T> result = new Result<T>();
this.tasks.add(new Work<T>(result, task));
return result;
}
}
The main thread is as below :
public void test() throws InterruptedException {
int count = 0;
ReusableThread<Integer> rt = new ReusableThread();
rt.start();
Thread.sleep(1000);
System.out.println("Thread-"+ count +" starting");
Result<Integer> result = rt.submit(JavaUtils::task);
System.out.println("In main : " + rt.getTasks().size()); //This prints 1
}
I think there is a thread-safety problem. Specifically:
a LinkedList is not thread-safe, and
you are using the LinkedList object in rt.getTasks().size() without any synchronization.
This is sufficient to cause size() to return a stale value under some circumstances.
If you are going to rely on the semantics of volatile you need to do a proper analysis of the happens-before relationships for each write / read sequence that matters to thread safety. It is tricky.
My advice would be:
Don't use volatile. Use synchronized and/or an existing thread-safe data structure instead ... if you need to reinvent the wheel.
Don't reinvent the wheel. You could replace your thread pool with a single call Executors.singleThreadExecutor; see javadoc.
You're missing synchronize 'tasks', so two thread (main and ReusableThread) random access to tasks, so you will not know what happen, I've modified your code:
import java.util.LinkedList;
import java.util.Queue;
class Result<T> {
}
interface Taskable<T> {
T run();
}
class JavaUtils {
public static Integer task() {
return 1;
}
}
public class ReusableThread<T> extends Thread{
private volatile Queue<Work<T>> tasks = new LinkedList<Work<T>>();
private Work<T> currentWork;
private class Work<T>{
Result<T> result;
Taskable<T> task;
public Work(Result<T> result, Taskable<T> task) {
this.result = result;
this.task = task;
}
}
#Override
public void run() {
while(true){
//System.out.println("ReusableThread.run()");
synchronized (tasks) {
if (!tasks.isEmpty()) {
System.out.println("Inside thread : " + tasks.size()); //This print 0
currentWork = tasks.remove();
T value = currentWork.task.run();
//currentWork.result.setValue(currentWork.task.run());
}
}
//currentWork.result.setComplete(true);
}
}
public Work<T> getWork() {
synchronized (tasks) {
return tasks.remove();
}
}
public Queue<Work<T>> getTasks() {
synchronized (tasks) {
return tasks;
}
}
public int getTaskSize() {
synchronized (tasks) {
return tasks.size();
}
}
public Result<T> submit(Taskable<T> task) {
Result<T> result = new Result<T>();
synchronized (tasks) {
this.tasks.add(new Work<T>(result, task));
}
return result;
}
public static void test() throws InterruptedException {
int count = 0;
ReusableThread<Integer> rt = new ReusableThread();
rt.start();
Thread.sleep(10);
System.out.println("Thread-"+ count +" starting");
Result<Integer> result = rt.submit(JavaUtils::task);
System.out.println("In main : " + rt.getTaskSize()); //This prints 1
}
public static void main(String[] args) throws Exception {
test();
}
}
and you should add Thread.sleep() to while(true) loop, If don't you will get 100% cpu soon
So my task is this:
Instantiate two object of the same class
Provide a constructor argument, to designate a thread as even and another as odd .
Start both threads right one after other
Odd thread prints odd numbers from 0 to 1000
Even thread prints even numbers from 0 to 1000
However they should be in sync the prints should be 1 , 2 , 3 , 4 .....
One number on each line
However I can't seem to get the locks to release correctly. I've tried reading some of the similar problems on here but they all use multiple classes. What am I doing wrong?
Edit: My main class is doing this -
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
and my output is -
odd: 1
even: 2
...
public class NumberPrinter extends Thread {
private String name;
private int starterInt;
private boolean toggle;
public NumberPrinter(String name) {
super.setName(name);
this.name=name;
if(name.equals("odd")) {
starterInt=1;
toggle = true;
}
else if(name.equals("even")) {
starterInt=2;
toggle = false;
}
}
#Override
public synchronized void run() {
int localInt = starterInt;
boolean localToggle = toggle;
if(name.equals("odd")) {
while(localInt<1000) {
while(localToggle == false)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = false;
notify();
}
}
else {
while(localInt<1000) {
while(localToggle == true)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = true;
notify();
}
}
}
}
The key problem here is that the two threads have no way to coordinate with each other. When you have a local variable (localToggle in this case) nothing outside the method can observe or alter its value.
If you share one object with both threads, however, its state can change, and if used correctly, those state changes will be visible to both threads.
You will see examples where the shared object is an AtomicInteger, but when you use synchronized, wait() and notify(), you don't need the extra concurrency overhead built into the atomic wrappers.
Here's a simple outline:
class Main {
public static main(String... args) {
Main state = new Main();
new Thread(new Counter(state, false)).start();
new Thread(new Counter(state, true)).start();
}
int counter;
private static class Counter implements Runnable {
private final Main state;
private final boolean even;
Counter(Main state, boolean even) {
this.state = state;
this.even = even;
}
#Override
public void run() {
synchronized(state) {
/* Here, use wait and notify to read and update state.counter
* appropriately according to the "even" flag.
*/
}
}
}
}
I'm not clear whether using wait() and notify() yourself is part of the assignment, but an alternative to this outline would be to use something like a BlockingQueue to pass a token back and forth between the two threads. The (error-prone) condition monitoring would be built into the queue, cleaning up your code and making mistakes less likely.
I finally got it working in a way that meets the standards required by my assignment.
Thank you all for your input. I'll leave the answer here for anyone who might need it.
public class Demo {
public static void main(String[] args) {
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
System.out.println("Calling thread Done");
}
public class NumberPrinter extends Thread {
private int max = 1000;
static Object lock = new Object();
String name;
int remainder;
static int startNumber=1;
public NumberPrinter(String name) {
this.name = name;
if(name.equals("even")) {
remainder=0;
}else {
remainder=1;
}
}
#Override
public void run() {
while(startNumber<max) {
synchronized(lock) {
while(startNumber%2 !=remainder) {
try {
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": "+startNumber);
startNumber++;
lock.notifyAll();
}
}
}
}
I whould like to block a method execution from more thab 3 threads. The method can be executed recursively. I have following agly code. Can I achive this by using better way?
private static class MyHolder {
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
private static Set<Thread> asquiredThreads = new HashSet<Thread>();
}
#Override
public void someMethod() {
if (!MyHolder.asquiredThreads.contains(Thread.currentThread())) {
synchronized (MyHolder.asquiredThreads) {
if (!MyHolder.asquiredThreads.contains(Thread.currentThread())) {
try {
MyHolder.limitThreadsSemaphore.acquire();
MyHolder.asquiredThreads.add(Thread.currentThread());
} finally {
MyHolder.limitThreadsSemaphore.release();
MyHolder.asquiredThreads.remove(Thread.currentThread());
}
}
}
}
return super.someMethod();
}
Thanks.
The simplest approach would be to refactor the recursive method to be private and then have the public method unconditionally acquire the semaphore, call the private method and then release the semaphore again. The recursive calls route straight to the private method so don't go through the semaphore guard code.
If that is not an option then the simplest approach I can think of would be to use a ThreadLocal flag
ThreadLocal<Object> alreadyIn = new ThreadLocal<>();
public void someMethod() {
boolean needSem = (alreadyIn.get() == null);
if(needSem) {
semaphore.acquire();
alreadyIn.set(new Object());
}
try {
// do stuff
} finally {
if(needSem) {
alreadyIn.remove();
semaphore.release();
}
}
}
I guess "someMethod" is the method you want to block execution,yeah?. Why don'y you do this? :
private static class MyHolder {
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
public boolean semaphoreAdquired = false; //Make it private
public Semaphore getSemaphore()
{
return limitThreadsSemaphore;
}
}
#Override
public void someMethod() {
boolean ReleaseSemaphore = false;
if(!semaphoreAdquired)
{
MyHolder.getSemaphore().acquire();
semaphoreAdquired = true;
ReleaseSemaphore = true;
}
super.someMethod();
if(ReleaseSemaphore)
{
MyHolder.getSemaphore().release();
semaphoreAdquired = false;
}
}
Based on the documentation for Semaphor, this should be achievable using only acquire() and release() around the critical section. Also, you should be able to put the semaphor in the current class, no need for a separate class to contain the Semaphor.
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
#Override
public void someMethod() {
limitThreadsSemaphore.acquire();
// do work.
limitThreadsSemaphore.release();
}
Update: If you need to call a method recursively within a thread, then the easiest way is to use a helper method to acquire the semaphor, and then invoke the recursive method from that helper method after acquiring the sempahor. You would call the helper instead of the original method in all the initial calls.
private static Semaphore limitThreadsSemaphore = new Semaphore(3);
public void someMethodHelper() {
limitThreadsSemaphore.acquire();
someMethod();
limitThreadsSemaphore.release();
}
#Override
public void someMethod() {
// do work, with recursive calls.
}
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
Can someone please help me out.
I need to use two threads in a way that one thread will run permanently while(true) and will keep track of a positioning pointer (some random value coming in form a method). This thread has a logic, if the value equals something, it should start the new thread. And if the value does not equal it should stop the other thread.
Can someone give me some code snippet (block level) about how to realize this?
Create a class that implements Runnable. There you'll make a run() method.
Like:
public class StackOverflow implements Runnable{
private Thread t = null;
public void run(){
}
public void setAnotherThread(Thread t){
this.t = t;
}
}
On the main class, you'll create 2 instances of Thread based on the other class you created.
StackOverflow so1 = new StackOverflow();
StackOverflow so2 = new StackOverflow();
Thread t1 = new Thread(so1);
Thread t2 = new Thread(so2)
Then you set one thread in the other, so you can control it.
t1.setAnotherThread(so2);
t2.setAnotherThread(so1);
Then you do what you need to do.
Ok if I'm not mistaken, you want to have one class that could be run as a "Thread" or as a (lets call it) a "sub-Thread".
But how to do that with one run method? just declare a boolean variable that specifies whether the thread object is a sub-thread or a parent thread, and accordingly declare two constructors, one would create a parent thread and the other would create a sub thread, and to be able to stop the sub-thread declare another variable called stop that is default to false.
class ThreadExample extends Thread {
private boolean sub = false;
private ThreadExample subThread = null;
public boolean stop = false;
public ThreadExample() {
}
public ThreadExample(boolean sub) {
this.sub = sub;
}
public void run() {
if (sub) {
runSubMethod();
} else {
runParentMethod();
}
}
public void runParentMethod() {
boolean running = true;
while (running) {
if (getRandomValue() == some_other_value) {
if (getSubThread().isAlive()) {
continue;
}
getSubThread().start();
} else {
getSubThread().makeStop();
}
}
}
public void runSubMethod(){
while(true){
//do stuff
if (stop)
break;
}
}
public int getRandomValue() {
//your "Random Value"
return 0;
}
private ThreadExample getSubThread() {
if (subThread == null) {
subThread = new ThreadExample(true);
}
return subThread;
}
public void makeStop(){
stop = true;
}
}
Here is a simple idea how you can implement as many threads as you like in a class:
class MultipleThreads{
Runnable r1 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//-----
Runnable r2 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//--- continue as much you like
public static void main (String[] args){
Thread thr1 = new Thread(r1);
Thread thr2 = new Thread(r2);
thr1.start();
thr2.start();
}
}
Hope it helps!!
For communicating between the two threads, one simple solution is to set a boolean type volatile static variable, and have it set from one thread and put it in while(flag) condition in the other thread.
You can control the other thread using this method.
And if you have waiting processes or Thread.sleep() and you want to break the thread without having it to finish it, your interrupts by catching the exception.