How to demonstrate race conditions around values that aren't published properly? - java

I am reading "Java Concurrency in practice" and looking at the example code on page 51.
According to the book this piece of code is at risk of of failure if it has not been published properly. Because I like to code examples and break them to prove how they work. I have tried to make it throw an AssertionError but have failed. (Leading me to my previous question)
Can anyone post sample code so that an AssertionError is thrown? Rule: Do not modify the Holder class.
public class Holder{
private int n;
public Holder(int n){
this.n = n;
}
public void assertSanity(){
if (n != n) {
throw new AssertionError("This statement is false");
}
}
}
I have modified the class to make it more fragile but I still can not get an AssertionError thrown.
class Holder2 {
private int n;
private int n2;
public Holder2(int n) throws InterruptedException{
this.n = n;
Thread.sleep(200);
this.n2 = n;
}
public void assertSanity(){
if (n != n2) {
throw new AssertionError("This statement is false");
}
}
}
Is it possible to make either of the above classes throw an AssertionError? Or do we have to accept that they may occasionally do so and we can't write code to prove it?

I'd run this on a multiprocessor machine for a few hours and see what happens(remove the sleep if you use your Holder2). Such race conditions might be rare, or not existant on your particular machine - but atleast try to provoke these one on a million cases , by trying millions of times.
class Checker {
private Holder h;
public Checker() {
h = new Holder(42);
}
public void check() {
h.assertSanity();
}
public void create(int n) {
h = new Holder(n);
}
}
public class MyThread extends thread{
private bool check;
private final Checker c;
public MyThread(bool check,Checker c) {
this.check = check;
this.c = c;
}
public static void main(String[] args) {
Checker c = new Checker();
MyThread t1 = new MyThread(false,c);
MyThread t2 = new MyThread(true,c);
t1.start();
t2.start();
t1.join();
t2.join();
}
public void run() {
int n = 0;
while(true) {
if(check)
c.check();
else
c.create(n++);
}
}
}
}

As BobbyShaftoe said in the other thread, you can't rely on just running the code enough times to show that the error can or cannot happen. If you think about this from an Assembly level, it will be very hard for n != n as it is so few calls and relies on the process being switched out at a really precise time.
If you want to be able to show whether a concurrent system is provably valid it would be better to model it using something like Labelled Transition Systems. Try the LTSA tool if you're interested in proving concurrency or finding errors.
http://www.doc.ic.ac.uk/ltsa/

In the example the that book is giving the Holder class is not directly the cause of the problem, in fact it states that:
The problem here is not the Holder class itself, but that the Holder is not properly published. However, Holder can be made immune to improper publication by declaring the n field to be final, which would make Holder immutable; see Section 3.5.2.
Just prior to this it mentions the following code, which it the subject of the problem:
// Unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
So to re-create it you will need to create a publisher class and two threads, one that calls initialize and one that calls the assert.
Having said that, I tried to re-create it myself and still failed to do so :(
Below is my first attempt, however there is a better explanation of the problem at http://forums.oracle.com/forums/thread.jspa?threadID=1140814&tstart=195
public class HolderTest {
#Test
public void testHolder() throws Exception {
for (int i = 0; i < 1000000000; i++) {
final CountDownLatch finished = new CountDownLatch(2);
final HolderPublisher publisher = new HolderPublisher();
final Thread publisherThread = new Thread(new Publisher(publisher,
finished));
final Thread checkerThread = new Thread(new Checker(publisher,
finished));
publisher.holder = null;
publisherThread.start();
checkerThread.start();
finished.await();
}
}
static class Publisher implements Runnable {
private final CountDownLatch finished;
private final HolderPublisher publisher;
public Publisher(final HolderPublisher publisher,
final CountDownLatch finished) {
this.publisher = publisher;
this.finished = finished;
}
#Override
public void run() {
try {
publisher.initialize();
} finally {
finished.countDown();
}
}
}
static class Checker implements Runnable {
private final CountDownLatch finished;
private final HolderPublisher publisher;
public Checker(final HolderPublisher publisher,
final CountDownLatch finished) {
this.publisher = publisher;
this.finished = finished;
}
#Override
public void run() {
try {
publisher.holder.assertSanity();
} catch (final NullPointerException e) {
// This isnt the error we are interested in so swallow it
} finally {
finished.countDown();
}
}
}
static class HolderPublisher {
// Unsafe publication
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
}
}

I don't think the assertion error can occur without modifying the Holder class. I think the book is wrong.
The only reason to cause the assertion error is when assertSanity() is called on a partially constructed object. How can a thread, other than the constructor thread, reference a partially constructed object? AFAIK, it's only possible in the following two cases:
Publish this in the constructor. E.g. assign this to a shared variable. This can't happen in our sample code because Holder's constructor doesn't do that.
A class's non-static inner class can refer to its parent even when its parent is partially constructed. This can't happen either because Holder doesn't have any inner class.
Note that the following code in the book doesn't publish any partially constructed object:
public class GoodCode {
public Holder holder;
public void initialize () {
holder = new Holder(42);
}
}
If you disassemble initialize(), you get the following:
public void initialize();
Code:
0: aload_0
1: new #2 // class Holder
4: dup
5: bipush 42
7: invokespecial #3 // Method Holder."<init>":(I)V
10: putfield #4 // Field holder:LHolder;
13: return
Note that putfield holder executes after invokespecial <init>. This means the assignment of holder happens after the constructor is completed. The partially constructed object is only stored in the thread's stack. It's not published.
If you can trigger the assertion error in a reasonable way (e.g. reflection is not reasonable), put it here. I will up vote you.

You cant change value of n at any time by using:
Holder h = new Holder(5);
Field f = h.getClass().getDeclaredField("n");
f.setAccessible(true);
f.setInt(h, 10);
h.assertSanity();

Related

Read field stale value after object construction

I'm reading a book "Java concurrency in practice" by Brian Goetz. Paragraphs 3.5 and 3.5.1 contains statements that I can not understand.
Consider the following code:
public class Holder {
private int value;
public Holder(int value) {
this.value = value;
}
public void assertValue() {
if (value != value) throw new AssertionError("Magic");
}
}
class HolderContainer {
// Unsafe publication
public Holder holder;
public void init() {
holder = new Holder(42);
}
}
Author states that:
In Java, Object constructor first writes default values to all fields before subclass constructor run.
Therefore it's possible to see field default value as a stale value.
Thread may see stale value the first time it reads a field and then a more up-to-date value the next time, which is why assertN  can throw AssertionError.
So, according to the text, with some unlucky timing it is possible that value = 0; and in the next moment value = 42.
I agree with point 1 that Object constructor firstly fills fields with default values. But I don't understand points 2 & 3.
Let's update authors code and consider the following example:
public class Holder {
int value;
public Holder(int value) {
//Sleep to prevent constructor to finish too early
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.value = value;
}
public void assertValue() {
if(value != value) System.out.println("Magic");
}
}
I've added Thread.sleep(3000), to force thread to wait before object will be fully constructed.
public class Tests {
private HolderContainer hc = new HolderContainer();
class Initialization implements Runnable {
public void run() {
hc.init();
}
}
class Checking implements Runnable {
public void run() {
hc.holder.assertValue();
}
}
public void run() {
new Thread(new Initialization()).start();
new Thread(new Checking()).start();
}
}
In example:
first thread inits holder object
second thread calls assertValue
Main Thread runs two threads:
new Thread(new Initialization()).start(); It tooks 3 seconds to fully construct Holder object
new Thread(new Checking()).start(); since Holder object still not constructed code will throw an NullPointerException
Therefore, it's impossible to emulate situation when field has default value.
My Questions:
Author was wrong about this concurrency problem?
Or It it impossible to emulate behaviour for fields default values?
I tried to test the problem with the following code.
Test:
public class Test {
public static boolean flag =true;
public static HolderContainer hc=new HolderContainer();
public static void main (String args[]){
new Thread(new Initialization()).start();
new Thread(new Checking()).start();
}
}
class Initialization implements Runnable {
public void run() {
while (Test.flag){
Test.hc=new HolderContainer();
Test.hc.init();
}
}
}
class Checking implements Runnable {
public void run() {
try{
Test.hc.holder.assertValue();
}
catch (NullPointerException e) {
}
}
}
Holder:
public class Holder {
private int value;
public Holder(int value) {
this.value = value;
}
public void assertValue() {
if (value != value) {
System.out.println("Magic");
Test.flag=false;
}
}
}
class HolderContainer {
public Holder holder;
public void init() {
holder = new Holder(42);
}
}
I never got the program to evaluate value!=value to true.
I don't think this proves anything and didn't run it for more than a couple minutes, but I hope this will be a better starting point for a well designed test or at least help to figure out some possible flaws in the tests.
I tried to insert a sleep between Test.hc=new HolderContainer(); and Test.hc.init();, between public Holder holder; and public void init() { and after public void init() {.
I am also concerned that checking if a value is null or catching the NullPoiterException may affect the timing too much.
Please note that the currently accepted answer to Improper publication of Java Object Reference says this problem is probably impossible under an x86 architecture. It may also be JVM dependent.
You are probably trying to simulate a concurrency scenario, which I believe is very hard to simulate using a couple of threads.
The following test-case which you have written is not correct at all is more likely to throw a NullPointerException.
public class Tests {
private HolderContainer hc = new HolderContainer();
class Initialization implements Runnable {
public void run() {
hc.init();
}
}
class Checking implements Runnable {
public void run() {
hc.holder.assertValue();
}
}
public void run() {
new Thread(new Initialization()).start();
new Thread(new Checking()).start();
}
}
What if your Checking Thread executes before Initialization one??
Also putting a sleep there simply means that executing thread will sleep and does tell you about the internal atomic operations being performed by then.
Did not reproduce it with your code. Here is an example to emulate un-safe publication. The strategy is let one thread publication Holder and let another check its value.
class Holder {
private volatile int value;
public Holder(int value, HolderContainer container) {
container.holder = this; // publication this object when it is not initilized properly
try {
Thread.sleep(10);
} catch (Exception e) {
}
this.value = value; // set value
}
public int getValue() {
return value;
}
}
class HolderContainer {
public Holder holder;
public Holder getHolder() {
if (holder == null) {
holder = new Holder(42, this);
}
return holder;
}
}
public class Tests {
public static void main(String[] args) {
for (int loop = 0; loop < 1000; loop++) {
HolderContainer holderContainer = new HolderContainer();
new Thread(() -> holderContainer.getHolder()).start();
new Thread(() -> {
Holder holder = holderContainer.getHolder();
int value1 = holder.getValue(); // might get default value
try {
Thread.sleep(10);
} catch (Exception e) {
}
int value2 = holder.getValue(); // might get custom value
if (value1 != value2) {
System.out.println(value1 + "--->" + value2);
}
}).start();
}
}
}
Sleeping 3 seconds before assigning the field in the constructor does not matter because for value != value to be true, the first read of value must produce a different result than the second one, which happens immediately after.
The Java Memory Model does not guarantee that values assigned to fields in constructors are visible to other threads after the constructor finishes.
To have this guarantee, the field must be final.
Here's a program that produces the bug on x86.
It must be run with the VM option: -XX:CompileCommand=dontinline,com/mypackage/Holder.getValue
package com.mypackage;
public class Test {
public static void main(String[] args) {
new Worker().start();
int i = 1;
while (true) {
new Holder(i++);
}
}
}
class Holder {
private int value;
Holder(int value) {
Worker.holder = this;
this.value = value;
}
void assertSanity() {
if (getValue() != getValue()) throw new AssertionError();
}
private int getValue() { return value; }
}
class Worker extends Thread {
static Holder holder = new Holder(0);
#Override
public void run() {
while (true) {
holder.assertSanity();
}
}
}
By disallowing Holder#getValue() to be inlined, we prevent the two subsequent reads of value to be collapsed into a single one.
This optimization prevents the code in the book from producing the bug.
However, the book author is still correct, since this optimization is not mandatory, so from the Java Memory Model perspective, the code is incorrect.
The assertSanity() method is equal to:
int snapshot1 = getValue();
// <--- window of vulnerability, where the observed value can change
// if you chose to sleep 3 seconds, you would want to do it here
// takes very little time, less than 1 nanosecond
int snapshot2 = getValue();
if (snapshot1 != snapshot2) throw new AssertionError();
So the first read of value could produce the default value of int which is 0 (called the stale value and assigned in the Object() constructor), and the second read could produce the value assigned in the Holder(int) constructor.
This would happen if for example the value assigned in the constructor were propagated to the thread calling assertSanity() in the exact moment between the two loads of value (window of vulnerability).
The same would happen if we delayed the second read in some other way, like:
int snapshot1 = this.value;
Thread.interrupted();
int snapshot2 = this.value;
if (snapshot1 != snapshot2) throw new AssertionError();

Unable to understand sync

Hey I am trying to make 10 threads in a synchronized manner and I came up with the code below however I am not able to understand a part of it as mentioned below. I am still really new to java, I tried looking up synchronized threading from
Here but still I am clueless.
class question3 {
public static void main(String arg[]) throws Exception {
for (int i = 0; i < 11; i++) {
data di = new data();
System.out.println(di.count);
}
}
}
class item {
static int count = 0;
}
class data extends item implements Runnable {
item d = this;
Thread t;
data() {
t = new Thread(this);
t.start();
}
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}
I am not sure what this part of code does?
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}
the run function is used when starting the thread, this is a must function you need to override when implement Runnable. When calling Thread.start(), the run function will be called.
The class syn contains a synchronized method, it is simply mean that only one thread can access it each time, thus make the incerment function thread safe.
object d has a static variable count meaning all instances of item class (and data ) share the same count, so all threads increment the same variable
the line d = syn.increment(d); is basically count++ but in a thread safe way

What is the purpose of defining an inner class within a static method?

I was reading the book "Head First Java" and at some point it mentioned that an inner class instance must be tied to an outer class instance, which I was already aware of, but with an exception:
A very special case—an inner class defined within a static method. But
you might go your entire Java life without ever encountering one of
these.
I'm pretty sure that last statement is indeed true, but if the compiler allows it to happen it means that it exists for a reason, otherwise it would be illegal Java. Can someone show me an example of where this would be useful?
It may be special, it may not be.
You're looking at a local class available within a method:
class Foo {
static void bar(){
class MyRunnable implements Runnable {
public void run() {
System.out.println("No longer anonymous!");
}
};
Thread baz = new Thread(new MyRunnable());
}
}
I've seen uses of inner classes that are anonymous like:
class Foo {
static void bar(){
Thread baz=new Thread(new Runnable(){
public void run(){
System.out.println("quux");
}
}
}
}
This is technically an inner class(though anonymous) and defined in a static method. I personally would create a static nested class that implements Runnable and do:
baz = new Thread(new MyRunnable());
where MyRunnable is defined as:
class Foo {
static void bar(){
// SNIP
}
static class MyRunnable implements Runnable {
public void run() {
System.out.println("No longer anonymous!");
}
}
}
Some people take the view that any method that can be static should be static. To such a person, the inner-beauty of the class would not be terribly relevant.
Here's a fabricated example of an inner class within a static method. It can be claimed that
It does not need to be declared outside the static method as it is not required elsewhere
It should be a named class (i.e. not anonymous) as it is being used multiple times
class Race {
public static void main(String[] args) throws Exception{
class Runner implements Runnable {
final String name;
long time = -1;
Runner(String name) { this.name = name; }
public void run() {
try {
long start = System.currentTimeMillis();
time = -2;
System.out.printf("Start %s\n", name);
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
}
System.out.printf("End %s\n", name);
this.time = System.currentTimeMillis() - start;
} catch (InterruptedException e) {
time = -3;
}
}
long time() { return time; }
}
Runner r1 = new Runner("One");
Runner r2 = new Runner("Two");
Thread one = new Thread(r1);
Thread two = new Thread(r2);
one.start();
two.start();
one.join();
two.join();
System.out.printf("One: %s, Two: %s\n", r1.time(), r2.time());
System.out.printf("%s wins\n", r1.time() < r2.time() ? "one" : "two");
}
}
I don't know the full context, but closures (i.e. Guava's Function implementation) and implementations defined in an utility class could be an example.
However, after searching for a while, I haven't found anonymous closure examples in Guava itself.

Java guarantees initialization safety for immutable objects?

To prove initialization safety for immutable objects, I wrote a small program. Even though fields were final, second thread was able to view the half-constructed object being created by the first thread. Have I got the concept wrong or "object escaping" can cause it? Second thread first printed "10 null" and then after half of the iterations it started printing "10 apple".
package test;
import java.util.ArrayList;
import java.util.List;
public final class ObjectEscape implements Runnable {
private final int a;
private final String b;
//this list is defined somewhere else
public static volatile List<ObjectEscape> globalList = new ArrayList<ObjectEscape>();
public ObjectEscape () throws InterruptedException {
a = 10;
globalList.add(this);
Thread.sleep(10);
b = "apple";
System.out.println("done");
}
public ObjectEscape(int a) {
this.a = 1;
b = "";
}
public static void main(String are[]) throws InterruptedException{
Thread t = new Thread(new ObjectEscape(1));
t.start();
ObjectEscape oe1 = new ObjectEscape();
}
#Override
public void run() {
int i=0;
while(i<10) {
if(globalList.get(0) != null)
System.out.println(globalList.get(0).a+" "+globalList.get(0).b);
i++;
}
}
}
final fields are guaranteed to have been initialized when the contructor call finishes. Naturally, a "leaking this" will subvert the value of this guarantee:
globalList.add(this); // ObjectEscape.<init> has not finished yet
See also: Java leaking this in constructor

How can I pass a parameter to a Java Thread?

Can anyone suggest to me how I can pass a parameter to a thread?
Also, how does it work for anonymous classes?
You need to pass the parameter in the constructor to the Runnable object:
public class MyRunnable implements Runnable {
public MyRunnable(Object parameter) {
// store parameter for later user
}
public void run() {
}
}
and invoke it thus:
Runnable r = new MyRunnable(param_value);
new Thread(r).start();
For Anonymous classes:
In response to question edits here is how it works for Anonymous classes
final X parameter = ...; // the final is important
Thread t = new Thread(new Runnable() {
p = parameter;
public void run() {
...
};
t.start();
Named classes:
You have a class that extends Thread (or implements Runnable) and a constructor with the parameters you'd like to pass. Then, when you create the new thread, you have to pass in the arguments, and then start the thread, something like this:
Thread t = new MyThread(args...);
t.start();
Runnable is a much better solution than Thread BTW. So I'd prefer:
public class MyRunnable implements Runnable {
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void run() {
}
}
Thread t = new Thread(new MyRunnable(parameter));
t.start();
This answer is basically the same as this similar question: How to pass parameters to a Thread object
via constructor of a Runnable or Thread class
class MyThread extends Thread {
private String to;
public MyThread(String to) {
this.to = to;
}
#Override
public void run() {
System.out.println("hello " + to);
}
}
public static void main(String[] args) {
new MyThread("world!").start();
}
This answer comes very late, but maybe someone will find it useful. It is about how to pass a parameter(s) to a Runnable without even declaring named class (handy for inliners):
String someValue = "Just a demo, really...";
new Thread(new Runnable() {
private String myParam;
public Runnable init(String myParam) {
this.myParam = myParam;
return this;
}
#Override
public void run() {
System.out.println("This is called from another thread.");
System.out.println(this.myParam);
}
}.init(someValue)).start();
Of course you can postpone execution of start to some more convenient or appropriate moment. And it is up to you what will be the signature of init method (so it may take more and/or different arguments) and of course even its name, but basically you get an idea.
In fact there is also another way of passing a parameter to an anonymous class, with the use of the initializer blocks. Consider this:
String someValue = "Another demo, no serious thing...";
int anotherValue = 42;
new Thread(new Runnable() {
private String myParam;
private int myOtherParam;
// instance initializer
{
this.myParam = someValue;
this.myOtherParam = anotherValue;
}
#Override
public void run() {
System.out.println("This comes from another thread.");
System.out.println(this.myParam + ", " + this.myOtherParam);
}
}).start();
So all happens inside of the initializer block.
When you create a thread, you need an instance of Runnable. The easiest way to pass in a parameter would be to pass it in as an argument to the constructor:
public class MyRunnable implements Runnable {
private volatile String myParam;
public MyRunnable(String myParam){
this.myParam = myParam;
...
}
public void run(){
// do something with myParam here
...
}
}
MyRunnable myRunnable = new myRunnable("Hello World");
new Thread(myRunnable).start();
If you then want to change the parameter while the thread is running, you can simply add a setter method to your runnable class:
public void setMyParam(String value){
this.myParam = value;
}
Once you have this, you can change the value of the parameter by calling like this:
myRunnable.setMyParam("Goodbye World");
Of course, if you want to trigger an action when the parameter is changed, you will have to use locks, which makes things considerably more complex.
I know that I'm a few years late, but I came across this issue and took an unorthodox approach. I wanted to do it without making a new class, so this is what I came up with:
int x = 0;
new Thread((new Runnable() {
int x;
public void run() {
// stuff with x and whatever else you want
}
public Runnable pass(int x) {
this.x = x;
return this;
}
}).pass(x)).start();
You can either extend the Thread class or the Runnable class and provide parameters as you want. There are simple examples in the docs. I'll port them here:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeThread p = new PrimeThread(143);
p.start();
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
To create a thread you normally create your own implementation of Runnable. Pass the parameters to the thread in the constructor of this class.
class MyThread implements Runnable{
private int a;
private String b;
private double c;
public MyThread(int a, String b, double c){
this.a = a;
this.b = b;
this.c = c;
}
public void run(){
doSomething(a, b, c);
}
}
Either write a class that implements Runnable, and pass whatever you need in a suitably defined constructor, or write a class that extends Thread with a suitably defined constructor that calls super() with appropriate parameters.
In Java 8 you can use lambda expressions with the Concurrency API & the ExecutorService as a higher level replacement for working with threads directly:
newCachedThreadPool() Creates a thread pool that creates new threads
as needed, but will reuse previously constructed threads when they are
available. These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks.
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
See also executors javadocs.
As of Java 8, you can use a lambda to capture parameters that are effectively final. For example:
final String param1 = "First param";
final int param2 = 2;
new Thread(() -> {
// Do whatever you want here: param1 and param2 are in-scope!
System.out.println(param1);
System.out.println(param2);
}).start();
Parameter passing via the start() and run() methods:
// Tester
public static void main(String... args) throws Exception {
ThreadType2 t = new ThreadType2(new RunnableType2(){
public void run(Object object) {
System.out.println("Parameter="+object);
}});
t.start("the parameter");
}
// New class 1 of 2
public class ThreadType2 {
final private Thread thread;
private Object objectIn = null;
ThreadType2(final RunnableType2 runnableType2) {
thread = new Thread(new Runnable() {
public void run() {
runnableType2.run(objectIn);
}});
}
public void start(final Object object) {
this.objectIn = object;
thread.start();
}
// If you want to do things like setDaemon(true);
public Thread getThread() {
return thread;
}
}
// New class 2 of 2
public interface RunnableType2 {
public void run(Object object);
}
You can derive a class from Runnable, and during the construction (say) pass the parameter in.
Then launch it using Thread.start(Runnable r);
If you mean whilst the thread is running, then simply hold a reference to your derived object in the calling thread, and call the appropriate setter methods (synchronising where appropriate)
There is a simple way of passing parameters into runnables.
Code:
public void Function(final type variable) {
Runnable runnable = new Runnable() {
public void run() {
//Code adding here...
}
};
new Thread(runnable).start();
}
No you can't pass parameters to the run() method. The signature tells you that (it has no parameters). Probably the easiest way to do this would be to use a purpose-built object that takes a parameter in the constructor and stores it in a final variable:
public class WorkingTask implements Runnable
{
private final Object toWorkWith;
public WorkingTask(Object workOnMe)
{
toWorkWith = workOnMe;
}
public void run()
{
//do work
}
}
//...
Thread t = new Thread(new WorkingTask(theData));
t.start();
Once you do that - you have to be careful of the data integrity of the object you pass into the 'WorkingTask'. The data will now exist in two different threads so you have to make sure it is Thread Safe.
One further option; this approach lets you use the Runnable item like an asynchronous function call. If your task does not need to return a result, e.g. it just performs some action you don't need to worry about how you pass back an "outcome".
This pattern lets you reuse an item, where you need some kind of internal state. When not passing parameter(s) in the constructor care is needed to mediate the programs access to parameters. You may need more checks if your use-case involves different callers, etc.
public class MyRunnable implements Runnable
{
private final Boolean PARAMETER_LOCK = false;
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void setParameter( final X newParameter ){
boolean done = false;
synchronize( PARAMETER_LOCK )
{
if( null == parameter )
{
parameter = newParameter;
done = true;
}
}
if( ! done )
{
throw new RuntimeException("MyRunnable - Parameter not cleared." );
}
}
public void clearParameter(){
synchronize( PARAMETER_LOCK )
{
parameter = null;
}
}
public void run() {
X localParameter;
synchronize( PARAMETER_LOCK )
{
localParameter = parameter;
}
if( null != localParameter )
{
clearParameter(); //-- could clear now, or later, or not at all ...
doSomeStuff( localParameter );
}
}
}
Thread t = new Thread(new MyRunnable(parameter));
t.start();
If you need a result of processing, you will also need to coordinate completion of MyRunnable when the sub-task finishes. You could pass a call back or just wait on the Thread 't', etc.
Specially for Android
For callback purposes I usually implement my own generic Runnable with input parameter(s):
public interface Runnable<TResult> {
void run(TResult result);
}
Usage is simple:
myManager.doCallbackOperation(new Runnable<MyResult>() {
#Override
public void run(MyResult result) {
// do something with the result
}
});
In manager:
public void doCallbackOperation(Runnable<MyResult> runnable) {
new AsyncTask<Void, Void, MyResult>() {
#Override
protected MyResult doInBackground(Void... params) {
// do background operation
return new MyResult(); // return resulting object
}
#Override
protected void onPostExecute(MyResult result) {
// execute runnable passing the result when operation has finished
runnable.run(result);
}
}.execute();
}
Create a local variable in your class that extends Thread or implements Runnable.
public class Extractor extends Thread {
public String webpage = "";
public Extractor(String w){
webpage = w;
}
public void setWebpage(String l){
webpage = l;
}
#Override
public void run() {// l is link
System.out.println(webpage);
}
public String toString(){
return "Page: "+webpage;
}}
This way, you can pass a variable when you run it.
Extractor e = new Extractor("www.google.com");
e.start();
The output:
"www.google.com"
First I want to point out that other answers are true.
However, using the parameter in the constructor may not be the best idea for all of you.
In many scenarios you will want to use "Anonymous Inner Class", and override the run() method, because defining specific class for every use is painful.
(new MyRunnable(){...})
And at the time you create that Runnable, the parameter may not be available to you to pass it in the constructor. If for example, you pass this object to a method, that will perform some work in separate thread and then call your runnable, applying the result from that work to it.
In that case, using a method like this one:
public MyRunnable withParameter(Object parameter), may turn out to be far more useful choice.
I do not claim that this is the best solution to the problem, but it will get the job done.

Categories