Ι 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.
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.
I have to create a method to calculate the sum of all elements in an array. The caveat is that the array is divided into a number of parts for many threads to calculate these parts simultaneously, and then combine to calculate the sum
All of these are restricted to inside the method code. The problem is when I write:
Thread t = new Thread(()->{
int sum=0;
//do some calculations
//time to pass this result back to the main method
});
The local anonymous class can only access final or effectively final local variable of the main method, which means I can't create a local variable and then change it to update the result. I can't think of a way to pass a thread's result back to combine with the results from the other threads.
Is there any way to solve this?
You can divide up the work in your main thread and do something like this:
public class Foo implements Runnable {
private volatile CustomArray<Integer> arr;
private volatile Integer sum;
public Foo(CustomArray<Integer> arr) {
this.arr = arr;
}
#Override
public void run() {
synchronized(this.arr) {
sum = arr.getSum();
}
}
public Integer getValue() {
synchronized(this.arr) {
return sum;
}
}
}
And call from another thread like so:
CustomArray<Integer> completeArray = new CustomArray<>(data);
ArrayList<CustomArray<Integer>> dividedArrays = completeArray.divideWork();
for(CustomArray<Integer> each : dividedArrays) {
Foo foo = new Foo(each);
new Thread(foo).start();
// ... join through some method
Integer value = foo.getValue();
}
Or, you can use an Executor and a Callable:
public void test() throws InterruptedException, ExecutionException
{
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Integer> callable = new Callable<Integer>() {
#Override
public Integer call() {
return 2;
}
};
Future<Integer> future = executor.submit(callable);
// returns 2 or raises an exception if the thread dies
Integer output = future.get();
executor.shutdown();
}
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;
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.
I want the main method to print out the value x, which is returned by running threads. How can I do it? Hope that my question makes sense.
import java.*;
public class ServerStudentThread extends Thread
{
public ServerStudentThread(Socket x) {
client = x;
}
public void run()
{
//Do something here and return an integer,
// for example **x**
}
public static void main(String args[]) throws Exception {
// ...
// I want to print out x value here.
// But as you can see, x disappears after thread finish its job.
}
}
You would have to make x a field in the ServerStudentThread class, not a local variable. then add a method in the class like getValue() that returns x. From the main method, after you create the thread, run it, call the getValue() mehod on the class to print get the value of x and print it.
If you are using java 5 there is an Callable Interface.kindly look at this link
http://java-x.blogspot.com/2006/11/java-5-concurrency-callable-and-future.html
// Code pasted from the link
public class CallableTester {
public static void main(String[] args) {
Callable<Integer> callable = new CallableImpl(2);
ExecutorService executor = new ScheduledThreadPoolExecutor(5);
Future<Integer> future = executor.submit(callable);
try {
System.out.println("Future value: " + future.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class CallableImpl implements Callable<Integer> {
private int myName;
CallableImpl(int i){
myName = i;
}
public Integer call() {
for(int i = 0; i < 10; i++) {
System.out.println("Thread : " + getMyName() + " I is : " + i);
}
return new Integer(getMyName());
}
public int getMyName() {
return myName;
}
public void setMyName(int myName) {
this.myName = myName;
}
}
You should create thread (call Thread t = new ServerStudentThread(), then call t.start() then you should wait until the tread is done. For example call t.join().