How would i pass an argument to the ScheduledThreadPoolExecutor?
I have the following code. You will notice that i have declared a variable 'num' and it is passed as an argument to exampleFunction(). exampleFunction contains a ScheduledThreadPoolExecutor. I want to be able to use the variable 'num' inside public void run(). Is there any way i can do that?
class Test {
...
int num;
exampleFunction(num);
...
public void exampleFunction(num) {
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.schedule(new Runnable() {
public void run() {
...do something here...
...something with 'num' here...
...i get an error when i try to use 'num' here
}
}, 10, TimeUnit.SECONDS);
}
}
Did you try changing exampleFunction(num) as exampleFunction(final int num)? Since run method is in an inner class all external bindings need to be final.
public void exampleFunction(final int num) { // final int here
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.schedule(new Runnable() {
public void run() {
...do something here...
...something with 'num' here...
...i get an error when i try to use 'num' here
}
}, 10, TimeUnit.SECONDS);
}
Either make num final or static (or accessible from a static method), or else create your own Runnable.
class MyRunnable implements Runnable {
int num;
public MyRunnable(int num) {
this.num = num;
}
public void run() { ... }
}
declare you variable num final and you will be able to use it inside the Run() method.
Write this instead
final int num;
Related
I have a thread created by implementing the Runnable interface. My task is this: the thread should count (starting from 0) and save the value it has reached to a variable which is part of the main class. I overrode the run method and did the counting but how I can save this value to the main's variable? Only with a getter is the solution?
My thread class:
public class myThread implements Runnable {
private static int count = 0;
private final int length;
public myThread (int length) {
this.length = length;
}
#Override
public void run() {
while (count < this.length) {
increaseValue();
}
}
private void increaseValue() {
synchronized (ThreadFirstExercise.class) {
if (count < this.length) {
this.count++;
}
}
}
}
main:
public class Main {
public static void main(String[] args) {
int result; // this is the variable where I want to save the counting result of my thread
(new Thread(new ThreadFirstExercise(10000))).start();
}
}
You can either use a Callable that returns a Future.
Or you could use a wrapper Object in the main method that contains the integer.
Ι have the following custom Runnable:
class RandomSum extends Runnable {
public void run() {
float sum - 0;
for(int i = 0; i<1000000;i++){
sum+=Math.random();
}
}
}
And I want to run it like that:
RandomSum s =new RandomSum();
s.retrieveCallback((sum)->{
System.out.println(sum);
});
Thread thread = new Thread();
thread.start();
But I do not know how I should define the method retrieveCallback in RandomSum that accepts a lambda?
You can define retrieveCallback within RandomSum as follows:
public void retrieveCallback(FeedbackHandler feedbackHandler) {
int sum = ...; // Get the value however you like.
feedbackHandler.handleFeedback(sum);
}
And then define this FeedbackHandler interface as:
public interface FeedbackHandler {
void handleFeedback(int sum);
}
Essentially what happens when you pass lambda (sum) -> {...} to retrieveCallback is:
retrieveCallback(new FeedbackHandler() {
#Override
public void handleFeedback(int sum) {
...
}
});
One possible target type of the lambda you've shown is a Consumer. Define a method setCallback accepting a Consumer<Float> and store it as an instance variable. Then invoke it after the for loop.
class RandomSum implements Runnable {
Consumer<Float> callback;
public void setCallback(Consumer<Float> callback) {
this.callback = callback;
}
public void run() {
float sum = 0;
for(int i = 0; i<1000000;i++){
sum += Math.random();
}
callback.accept(sum);
}
}
Caller side
RandomSum s =new RandomSum();
s.setCallback((sum)->{
System.out.println(sum);
});
Or using method references,
s.setCallback(System.out::println);
Preferably you can pass the callback in the constructor.
Thread t = new Thread(new Runnable() { public void run() {} });
I'd like to create a thread this way. How can I pass parameters to the run method if possible at all?
Edit: To make my problem specific, consider the following code segment:
for (int i=0; i< threads.length; i++) {
threads[i] = new Thread(new Runnable() {public void run() {//Can I use the value of i in the method?}});
}
Based on Jon's answer it won't work, since i is not declared as final.
No, the run method never has any parameters. You'll need to put the initial state into the Runnable. If you're using an anonymous inner class, you can do that via a final local variable:
final int foo = 10; // Or whatever
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println(foo); // Prints 10
}
});
If you're writing a named class, add a field to the class and populate it in the constructor.
Alternatively, you may find the classes in java.util.concurrent help you more (ExecutorService etc) - it depends on what you're trying to do.
EDIT: To put the above into your context, you just need a final variable within the loop:
for (int i=0; i< threads.length; i++) {
final int foo = i;
threads[i] = new Thread(new Runnable() {
public void run() {
// Use foo here
}
});
}
You may create a custom thread object that accepts your parameter, for example :
public class IndexedThread implements Runnable {
private final int index;
public IndexedThread(int index) {
this.index = index;
}
public void run() {
// ...
}
}
Which could be used like this :
IndexedThread threads[] = new IndexedThread[N];
for (int i=0; i<threads.length; i++) {
threads[i] = new IndexedThread(i);
}
So the situation is something like this:
private void myMethod()
{
System.out.println("Hello World"); //some code
System.out.println("Some Other Stuff");
System.out.println("Hello World"); //the same code.
}
We don't want to be repeating our code.
The technique described here works pretty well:
private void myMethod()
{
final Runnable innerMethod = new Runnable()
{
public void run()
{
System.out.println("Hello World");
}
};
innerMethod.run();
System.out.println("Some other stuff");
innerMethod.run();
}
But what if I want to pass in a parameter to that inner method?
eg.
private void myMethod()
{
final Runnable innerMethod = new Runnable()
{
public void run(int value)
{
System.out.println("Hello World" + Integer.toString(value));
}
};
innerMethod.run(1);
System.out.println("Some other stuff");
innerMethod.run(2);
}
gives me: The type new Runnable(){} must implement the inherited abstract method Runnable.run()
While
private void myMethod()
{
final Runnable innerMethod = new Runnable()
{
public void run()
{
//do nothing
}
public void run(int value)
{
System.out.println("Hello World" + Integer.toString(value));
}
};
innerMethod.run(1);
System.out.println("Some other stuff");
innerMethod.run(2);
}
gives me The method run() in the type Runnable is not applicable for the arguments (int).
Nope, that isn't a method but an anonymous object. You can create an extra method to use for the object.
Thread thread = new Thread( new Runnable()
{
int i,j;
public void init(int i, int j)
{
this.i = i;
this.j=j;
}
});
thread.init(2,3);
thread.start();
And wrap runnable in a Thread, and call start! Not run().
Because you can't call the constructor of an anonymous class, as pointed out by #HoverCraft you could extend a named class that implements Runnable.
public class SomeClass implements Runnable
{
public SomeClass(int i){ }
}
Looks like you just want inner methods. Java does't let you have them, so the Runnable hack you describe lets you sort-of declare an inner method.
But since you want more control over it, why not define your own:
interface Inner<A, B> {
public B apply(A a);
}
Then you can say:
private void myMethod(..){
final Inner<Integer, Integer> inner = new Inner<Integer, Integer>() {
public Integer apply(Integer i) {
// whatever you want
}
};
// then go:
inner.apply(1);
inner.apply(2);
}
Or use some library that provides functor objects. There should be many. Apache Commons has a Functor that you can use.
public static void main(String args[]) throws Exception {
int maxScore = 0;
Thread student = new Thread(client,????);
student.start();
}
I want student thread to change value of maxScore, how do I do it in Java? (Like in C we can pass the address of maxScore)
You need a class object, if you want to modify value in separate thread. For example:
public class Main {
private static class Score {
public int maxScore;
}
public static void main(String args[]) throws Exception {
final Score score = new Score();
score.maxScore = 1;
System.out.println("Initial maxScore: " + score.maxScore);
Thread student = new Thread() {
#Override
public void run() {
score.maxScore++;
}
};
student.start();
student.join(); // waiting for thread to finish
System.out.println("Result maxScore: " + score.maxScore);
}
}
You can't. There is no way you can change the value of a local variable from another thread.
You can, however, use a mutable type that has an int field, and pass it to the new thread. For example:
public class MutableInt {
private int value;
public void setValue(..) {..}
public int getValue() {..};
}
(Apache commons-lang provide a MutableInt class which you can reuse)
Update: for a global variable you can simple use public static fields. Note that if you are willing not only to store some values in them, but also read them and do stuff depending on that, you would need to use synchronized blocks, or AtomicInteger, depending on the usages.
Also, you can use array (of one element):
public class Main {
public static void main(String args[]) throws Exception {
final int[] score = new int[1];
score[0] = 1;
System.out.println("Initial maxScore: " + score[0]);
Thread student = new Thread() {
#Override
public void run() {
score[0]++;
}
};
student.start();
student.join(); // waiting for thread to finish
System.out.println("Result maxScore: " + score[0]);
}
}
adding Synchronized to the methods was a solution for me, thanks