Passing parameter to Java Thread - java

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);
}

Related

How to access class inside a thread

I am trying to do following in gui class for notifying registred observers.
public class GUI extends javax.swing.JFrame implements Observer {
public notImportantMethod() {
t = new Thread() {
#Override
public void run() {
for (int i = 1; i <= 10; i++) {
myObject.registerObserver(this);
}
}
};
t.start();
}
}
It gives me error: incompatible types: cannot be converted to Observer How can I use this? I know inside of run there is another context but how could I access it?
this now refers a Thread. You should be able to call GUI.this. For more info, see here .
If you're looking for quick and dirty: (this is not good practice)
public notImportantMethod() {
final GUI self = this;
t = new Thread() {
#Override
public void run() {
for (int i = 1; i <= 10; i++) {
myObject.registerObserver(self);
}
}
};
t.start();
}
}
Otherwise I would recommend looking up a tutorial on multi-threading and/or concurrency in java, like this one: http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
#Ishnark has answered it correctly. You should be able to access it via GUI.this, that's all that you need to do.

Assign a task to Thread and return from method. for example

public class MyThreadExample {
public static void main(String[] args) {
MyThreadExample myThreadExample = new MyThreadExample();
String country= myThreadExample.getCountry();
System.out.println(country);
}
public String getCountry() {
/* Question : */
return "India";
}
public void printValues() {
for(int i = 0 ; i < 200; ++i) {
System.out.println(i);
}
}
}
Label Question : I want call printValues() method and immediatly return from this method, can I use Thread here to call printValue()
The simplest way to run some code in a new thread, assuming you have a Java 8 compiler:
new Thread(() -> {
printValues();
}).start();
or assuming you don't have a Java 8 compiler:
new Thread() {
#Override
public void run() {
printValues();
}
}).start();
Note, however, that this might not do what you want.
(Some people will recommend using an Executor; when you only have one task to run, there is no difference in behaviour, but the Executor would add more complexity)
You need to use 'Futures'.
See 'Futures and Callables' here
Yes you can surely use Threads , I prefer ExecutorService mechanism ,
Here is how you do it :
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
public void run() {
for(int i = 0 ; i < 200; ++i) {
System.out.println(i);
}
}
});
executorService.shutdown();
You could rewrite your printValues() method this way to start a thread inside the method for the execution of what you want.
public void printValues() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0 ; i < 200; ++i) {
System.out.println(i);
}
}
});
t.start();
}

Nullpointer Exception and Threads

Consider the following code:
class Chicks {
synchronized void yack(long id) {
for(int x = 1; x < 3; x++) {
System.out.print(id + " ");
Thread.yield();
}
}
}
public class ChicksYack implements Runnable {
Chicks c; //.....(1)
public static void main(String[] args) {
new ChicksYack().go();
}
void go() {
c = new Chicks(); //........(2)
new Thread(new ChicksYack()).start();
new Thread(new ChicksYack()).start();
}
public void run() {
c.yack(Thread.currentThread().getId());
}
}
When i run this code, I am getting a Null Pointer Exception that I have not initialized variable c. But didn't i initialized it at line ....(2)? I am having trouble getting this concept. Does threading has a part to play in this exception?
Look at this line:
new Thread(new ChicksYack()).start();
^^^^^^^^^^^^^^^^
The attribute c of the newly created ChicksYack object is never initialized. In the go() method you only initialize c for the current (this) object.
That's why you get an NPE in the run() method. A good solution would be to initialize that variable in a default constructor for ChicksYack.
In the go() method, you're instantiating two new ChickYack objects, which have a null c. You should put the c = new Chicks() in your ChicksYack constructor.

Synchronized counter does not count correctly

For each creation of the object, I want it to be uniquely accessible by an identifier. I am using an incrementing static value to keep track of how many objects have been created, and every time a new one is constructed, I make its identifier equivalent to count + 1 (and increment the count). The problem I am encountering is that synchronization is not working. Here is a simplified version of the code:
public static final Hashtable MODULES = new Hashtable();
private static final Object countLock = new Object();
private static int count = 0;
private final String identifier;
private final String name;
public Class(String name) {
this.identifier = String.valueOf(incrementCount());
this.name = name;
MODULES.put(identifier, name);
}
private static int incrementCount() {
synchronized (countLock) {
return ++count;
}
}
Now when I test with this (unrealistically, admittedly, but to be sure that it works):
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
#Override
public void run() {
Class m = new Class("Name");
}
}).start();
}
System.out.println(Module.MODULES.size());
I get output anywhere from the 60's to 100. Obviously I don't want that sort of unreliability. Would a volatile field work here? (I have tried with the same results) I am not sure how to make sure every class object has a different identifier. Any solutions are welcome.
Note: I do not access to java.util.concurrent for implementation specific reasons.
Your lock is working fine but the problem is something different. You are initializing the each object through a new Thread. While the threads are running in background, the main thread, prints the count at moment. Put an appropriate delay in between, you will see the proper count.
public static void main(String[] args) throws InterruptedException{
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
#Override
public void run() {
Counter m = new Counter("Name");
}
}).start();
}
Thread.sleep(1000);//put a delay
System.out.println(MODULES.size());
}
Try this:
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
#Override
public void run() {
Class m = new Class("Name");
}
}).start();
}
Thread.sleep(500);
System.out.println(Module.MODULES.size());
You are printing the size of hashtable which is not synchronized.
add a synchronized statement before the statement MODULES.put(identifier, name);
synchronized (MODULES) {
MODULES.put(identifier, name);
}
it works for me.
Here is what I see as a problem in your code: The statement Class m = new Class("Name"); is in the run() function, and not in the constructor of Runnable's implementation in your code.
If I have to write a similar code, I would write it this way:
public class ModuleTest {
public static void main(String[] args) {
for (int x = 0; x < 100; x++) {
new Thread(new Runnable() {
{
Module m = new Module("Name");
}
#Override
public void run() {
// do something
}
}).start();
}
System.out.println(Module.MODULES.size());
}
}
Look at the placement of statement Module m = new Module("Name"); above. It is not in run() function, as run() is called when start() is called. That statement is between unnamed braces {} that is called during construction of the anonymous implementation of Runnable you have in your code.
And to complete the above code, here is the Module class:
import java.util.Hashtable;
public class Module {
public static final Hashtable MODULES = new Hashtable();
private static final Object countLock = new Object();
private static int count = 0;
private final String identifier;
private final String name;
public Module(String name) {
this.identifier = String.valueOf(incrementCount());
this.name = name;
MODULES.put(identifier, name);
}
private synchronized static int incrementCount() {
return ++count;
}
}

How to synchronize two methods

I have following code for a chat server application in Java -
public synchronized List<ChatMessage> getMessages(int messageNumber) {
return messages.subList(messageNumber + 1, messages.size());
}
public synchronized int addMessage(ChatMessage c) {
messages.add(c);
return messages.size()-1;
}
I have following test code -
public static void main(String[] args) {
final ChatRoom c = new ChatRoom();
Thread user1 = new Thread(new Runnable() {
public void run() {
for(int i=0;i<1000;i++) {
c.addMessage(new ChatMessage());
c.getMessages(0);
}
}
});
Thread user2 = new Thread(new Runnable() {
public void run() {
for(int i=0;i<1000;i++) {
c.addMessage(new ChatMessage());
c.getMessages(0).size();
}
}
});
user1.start();
user2.start();
}
I am getting a ConcurrentModificationException.
How is this possible?
How is this possible?
Your getMessages method just returns a view on the original list. It doesn't create a copy of the list. So one thread is using a view on the list while another modifies the list - at that point, you get the exception.
From the docs for List.subList:
The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list. (Structural modifications are those that change the size of this list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.)
It's not clear what you're really trying to achieve here, but fundamentally you can't use subList to magically create a thread-safe list :)
The simplest thing to do is to create a combined method
public synchronized int addMessageAndGetCount(ChatMessage c) {
messages.add(c);
return messages.size();
}
public static void main(String... args) {
final ChatRoom c = new ChatRoom();
final Runnable runner = new Runnable() {
public void run() {
for(int i = 0; i < 1000; i++) {
c.addMessageAndGetCount(new ChatMessage());
}
}
};
new Thread(runner).start();
new Thread(runner).start();
}
You cannot safely return a list or a subList from a synchronized block. You can return a copy but all you need is the size.

Categories

Resources