While doing some practices on multi-threading, I found that I can not set the name of the thread in my code. I can use this to refer the current object then why I can not use Thread.currentThread while constructing thread to access current thread. I am bit confusing. please help me.
When actually thread creating? Is it when constructing thread instance or while calling method start() on thread?
what is currentThread means here?
public class RecursiveRunnableTest {
public static void main(String... args){
Thread t = new Thread(new RecursiveRunnable("First thread"));
t.start();
}
}
class RecursiveRunnable implements Runnable {
private String name;
public RecursiveRunnable(String name) {
this.name = name;
Thread.currentThread().setName(this.name); // Expecting to set the name of thread here
}
#Override
public synchronized void run() {
System.out.println(Thread.currentThread().getName()); // displaying Thread-0
System.out.println(this.name); // displaying "First thread"
try{
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
}
}
}
Simply because main thread constructs it not the t thread constructs itself. So, you may rewrite to this one (setting thread's name before starting it):
public class RecursiveRunnableTest {
public static void main(String... args){
RecursiveRunnable rr = new RecursiveRunnable("First thread");
Thread t = new Thread(rr);
t.setName(rr.getName());
t.start();
}
}
class RecursiveRunnable implements Runnable{
private String name;
public RecursiveRunnable(String name) {
this.name = name;
}
public String getName(){return this.name;}
#Override
public synchronized void run() {
System.out.println(Thread.currentThread().getName()); // displaying Thread-0
System.out.println(this.name); // displaying "First thread"
try{
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
}
}
}
Try doing this instead
Thread t = new Thread(new RecursiveRunnable("First thread"));
t.start();
Thread.sleep(1L);
System.out.println("main thread: " + Thread.currentThread().getName()); // same thread that created the RecrusiveRunnable instance
you will see
main thread: First thread
printed.
This is because the main thread builds the RecursiveRunnable, so
Thread.currentThread().setName(this.name);
is actually changing the name of the main thread, not the thread that the Runnable will eventually run in.
Also
System.out.println(this.name); // displaying "First thread"
is referring to the name field of the RecursiveRunnable object, which you've set to the same value as the main thread.
Related
I have two classes, The first one is in charge of creating threads, then those threads need to be notified from the second class
Problem: I cannot find created threads from the second class, getThreadByName() always return null, Any Idea?.
FirstClass
public class class1{
protected void createThread(String uniqueName) throws Exception {
Thread thread = new Thread(new OrderSessionsManager());
thread.setName(uniqueName);
thread.start();
}
}
OrderSessionManager
public class OrderSessionsManager implements Runnable {
public OrderSessionsManager() {
}
#Override
public void run() {
try {
wait();
}catch(Exception e) {
e.printStackTrace();
}
}
SecondClass
public class class2{
protected void notifyThread(String uniqueName) throws Exception {
Thread thread = Utils.getThreadByName(uniqueName);
thread.notify();
}
}
Utils
public class Utils{
public static Thread getThreadByName(String threadName) {
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
int noThreads = currentGroup.activeCount();
Thread[] threads = new Thread[noThreads];
currentGroup.enumerate(threads);
List<String>names = new ArrayList<String>();
for (Thread t : threads) {
String tName = t.getName().toString();
names.add(tName);
if (tName.equals(threadName)) return t;
}
return null;
}
}
There are several issues with your code:
1) It breaks Java Code Conventions: class name must start with a
capital letter
2) wait() method must be called by a thread who owns the object's monitor
so you must use something like:
synchronized (this) {
wait();
}
3) notify() method must be called by a thread who owns the object's monitor and by the same object as wait(), in your case OrderSessionsManager's instance.
4) Since you do not specify a ThreadGroup, the thread gets it's ThreadGroup from it's parent. The following code works as expected:
public class Main {
public static void main(String[] args) {
class1 c1 = new class1();
try {
c1.createThread("t1");
} catch (Exception e) {
e.printStackTrace();
}
Thread thread = Utils.getThreadByName("t1");
System.out.println("Thread name " + thread.getName());
}
}
but this happens only because the t1 thread is in the same group as the main thread.
I want to create two Threads.One to display something and after that it will go to Wait state.Then the second thread should start executing and it should print the state of the first thread(i.e waiting state) and after displaying it should notify and the first Thread should continue executing.
I have created a small program for you. Please check if it meets your requirement. We can beautify the code later. Please elaborate your requirements more, if it is not meeting your expectations.
public class Main {
public static void main(String[] args) {
MyThread1 th1 = new MyThread1();
MyThread2 th2 = new MyThread2();
//Allow thread 1 to run first
Shareable shareable = new Shareable();
shareable.threadToRun = th1.getName();
th1.setAnotherThread(th2);
th1.setShareable(shareable);
th2.setAnotherThread(th1);
th2.setShareable(shareable);
th1.start();
th2.start();
}
}
class Shareable {
volatile String threadToRun;
}
class MyThread1 extends Thread {
private Shareable shareable;
private Thread anotherThread;
#Override
public void run() {
synchronized (shareable) {
waitForTurn();
System.out.println(getName() + " I am doing first task. After that wait for next Thread to finish.");
shareable.threadToRun = anotherThread.getName();
shareable.notifyAll();
waitForTurn();
System.out.println(getName() + " I am doing next task now.");
}
}
private void waitForTurn(){
if(!shareable.threadToRun.equals(getName())){
try {
shareable.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void setShareable(Shareable shareable){
this.shareable = shareable;
}
public void setAnotherThread(Thread anotherThread){
this.anotherThread = anotherThread;
}
}
class MyThread2 extends Thread {
private Shareable shareable;
private Thread anotherThread;
#Override
public void run() {
synchronized (shareable) {
waitForTurn();
System.out.println(getName() + " I am doing task now. Another Thread " + anotherThread.getName() + " is in state " + anotherThread.getState());
shareable.threadToRun = anotherThread.getName();
shareable.notifyAll();
}
}
private void waitForTurn(){
if(!shareable.threadToRun.equals(getName())){
try {
shareable.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void setShareable(Shareable shareable){
this.shareable = shareable;
}
public void setAnotherThread(Thread anotherThread){
this.anotherThread = anotherThread;
}
}
Here is the output:
Thread-0 I am doing first task. After that wait for next Thread to finish.
Thread-1 I am doing task now. Another Thread Thread-0 is in state WAITING
Thread-0 I am doing next task now.
public class TestSynchronization {
public static void main(String[] args) {
ThreadTest[] threads = new ThreadTest[10];
int i = 0;
for(Thread th : threads) {
th = new Thread(Integer.toString(i++));
th.start();
}
}
class ThreadTest extends Thread {
TestSynchronization ts = new TestSynchronization();
public /*synchronized */void run() {
synchronized(this) {
ts.testingOneThreadEntry(this);
System.out.println(new Date());
System.out.println("Hey! I just came out and it was fun... ");
this.notify();
}
}
}
private synchronized void testingOneThreadEntry(Thread threadInside) {
System.out.println(threadInside.getName() + " is in");
System.out.println("Hey! I am inside and I am enjoying");
try {
threadInside.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I am not able to start the ThreadTest instances.
I expect that ThreadTest's run method be executed as soon as the line th.start(); is executed, the one inside main method.
When I run the program, I see niether my system.out nor any exception.
I debugged also, but could see loop runs 10 times.
You just started a Thread, not a ThreadTest. Thread's run() method does nothing. Instead, create and start() a ThreadTest.
for(ThreadTest th : threads) {
th = new ThreadTest(Integer.toString(i++));
th.start();
}
You'll also need a one-arg constructor in your ThreadTest class that will take the String you're passing to it.
public ThreadTest(String msg){
super(msg);
}
You'll also need to make the ThreadTest class static so you can access that nested class from the static main method.
static class ThreadTest extends Thread {
However, you'll wind up will all Threads waiting. As written, this code will call wait inside every Thread, but it will never get to notify. The notify method must be called on the Thread to be notified, from another Thread. If it's waiting, then it can never notify itself.
You have array of ThreadTest (thread) class which is not used.
I assume you wanted this:
public static void main(String[] args) {
ThreadTest[] threads = new ThreadTest[10];
int i = 0;
for(int i=0;i<threads.length;i++) {
threads[i] = new ThreadTest();
threads[i].start();
}
}
I'm trying to interleave the execution of two independent threads. such that both have a run method with 10 iterations and after every iteration i want to context switch the threads.
thread A starts and after doing something like printing passes control to thread B. then thread B prints and passes control back to A and so on until both finish.
What is the effective mechanism to do this?
I'm attaching a sample code. hope you can help.
// Suspending and resuming a thread for Java 2
class NewThread implements Runnable {
String name; // name of thread
Thread t;
// boolean suspendFlag;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
// suspendFlag = false;
t.start(); // Start the thread
}
public String getState()
{
Thread t=Thread.currentThread();
return t.getState().toString();
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(200);
synchronized(this) {
//SuspendResume.suspendFlag2=false;
SuspendResume.suspendFlag1=true;
while(SuspendResume.suspendFlag1) {
wait();
//System.out.println(SuspendResume.ob1.t.getState().toString());
// if(SuspendResume.ob2.t.getState().toString()=="WAITING")
// SuspendResume.ob2.t.notify();
}
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
// suspendFlag = true;
}
synchronized void myresume() {
// suspendFlag = false;
notify();
}
}
class NewThread2 implements Runnable {
String name; // name of thread
Thread t;
// boolean suspendFlag;
NewThread2(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
// suspendFlag = false;
t.start(); // Start the thread
}
public String getState()
{
Thread t=Thread.currentThread();
return t.getState().toString();
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 15; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
synchronized(this) {
//SuspendResume.suspendFlag1=false;
//while(SuspendResume.suspendFlag1) {
// while(suspendFlag) {
//wait();
//System.out.println(SuspendResume.ob2.t.getState().toString());
//if(SuspendResume.ob1.t.getState().toString()=="WAITING")
//SuspendResume.ob1.t.notify();
//}
SuspendResume.suspendFlag1=false;
notify();
}
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
void mysuspend() {
// suspendFlag = true;
}
synchronized void myresume() {
// suspendFlag = false;
notify();
}
}
class SuspendResume {
static boolean suspendFlag1=false;
static NewThread ob1 = new NewThread("One");
static NewThread2 ob2 = new NewThread2("Two");
// static boolean suspendFlag2=false;
public static void main(String args[]) {
try {
//Thread.sleep(1000);
//ob1.mysuspend();
//System.out.println("Suspending thread One");
//Thread.sleep(1000);
//ob1.myresume();
//System.out.println("Resuming thread One");
// ob2.mysuspend();
//System.out.println("Suspending thread Two");
Thread.sleep(1000);
// ob2.myresume();
//System.out.println("Resuming thread Two");
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
System.out.println(ob1.getState());
System.out.println(ob1.getState());
ob1.t.join();
ob2.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Main thread exiting.");
}
}
First off, I'm not sure what kind of scenario you have where you want to run two threads sequentially over and over again. That sounds like a single thread running two different methods in a loop. None-the-less, it sounds like an interesting challenge so I took it up.
Making use of Java 5's Exchanger class, the solution gets pretty small. I ended up with a single Runnable class. I use two instances of them to pass around a boolean true and boolean false to each other. The Exchanger class facilitates the passing around of the boolean values in a thread safe manner. A Runnable only 'executes' its code when it has the boolean true value.
package interleavedexample;
import java.util.concurrent.Exchanger;
import java.util.logging.Logger;
/**
*
*/
public class InterleavedRunnable implements Runnable {
private final String name;
private final Exchanger<Boolean> exchanger;
private Boolean state;
public InterleavedRunnable(String name, Exchanger<Boolean> exchanger,
Boolean state) {
this.name = name;
this.exchanger = exchanger;
this.state = state;
}
#Override
public void run() {
try {
while (true) {
if (state) {
Logger.getLogger(getClass().getName()).info(name + " is running");
}
state = exchanger.exchange(state);
}
} catch (InterruptedException ex) {
Logger.getLogger(name).info("Interrupted");
}
}
Setting up the runnables are quite easy:
public static void main(String[] args) {
Exchanger<Boolean> exchanger = new Exchanger<Boolean>();
Thread thread1 = new Thread(new InterleavedRunnable("Thread 1", exchanger, true));
Thread thread2 = new Thread(new InterleavedRunnable("Thread 2", exchanger, false));
thread1.start();
thread2.start();
}
Anytime you can find existing functionality within the Java API (or well known libraries), you should utilize them to the fullest extent. The less lines of code you write the less lines there are to maintain.
The 'OS Sycnro 101' solution is to use two semaphores, one for each thread, and swap over one 'GO' token/unit between them. Start both threads and then give the token to whichever thread you want to go first.
Use wait and notify for this.
public class Thread1 implements Runnable {
#Override
public void run() {
while(true){
synchronized (Main.obj) {
try {
Main.obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("1");
synchronized (Main.obj) {
Main.obj.notify();
}
}
}
}
public class Thread2 implements Runnable{
#Override
public void run() {
while(true){
synchronized (Main.obj) {
try {
Main.obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("2");
synchronized (Main.obj) {
Main.obj.notify();
}
}
}
}
public class Main {
public volatile static Object obj = new Object();
/**
* #param args
*/
public static void main(String[] args) {
Thread t1 = new Thread(new Thread1());
Thread t2 = new Thread(new Thread2());
t1.start();
t2.start();
synchronized (obj) {
obj.notifyAll();
}
}
}
Did not get your question correctly. If you want to execute thread B only after thread A execution is over, then there is no point of multi-threading at all. You can simply put the thread B contents in thread A run() method.
Still if it is very much required then you can try using wait() and notify() methods on two objects . Something like this.
Class ClassA implements runnable{
Message messageA;
Message messageB;
public ClassA(Message messageA,,Message messageB){
this.messageA = messageA;
this.messageB = messageB;
}
public void run(){
for(;loop contition;){
//code here
messageB.notify();
messageA.wait();
}
}
}
Class ClassB implements runnable{
Message messageA;
Message messageB;
public ClassB(Message messageA,Message messageB){
this.messageA = messageA;
this.messageB = messageB;
}
public void run(){
for(;loop condition;){
messageB.wait();
//code here
messageA.notify();
}
}
}
now create two objects in main messageA and messageB and pass both of them in the constructor of each thread.
I have 2 classes. One method of the class calls the other class' method, but it has to wait until the method finishes to proceed to the execution of the rest of the code.
This is a rough code of what I'm trying to make. And I know this doesn't work.
public class Example
{
Thread thread;
public Example(Thread thread)
{
this.thread = thread;
}
public void doSomethingElse()
{
System.out.println("Do something else");
thread.notify();
}
}
public class Example2
{
Thread thread;
Example example;
public Example2()
{
example = new Example(thread);
thread = new Thread()
{
public void run()
{
example.doSomethingElse();
try {
this.wait();
} catch (InterruptedException ex) {
}
System.out.println("Do something");
}
};
}
public void doSomething()
{
thread.run();
}
}
Now do you know how to make this right?
Not sure if your constrained to using this particular approach (wait/notify) however a better approach is taking advantage of the Java Concurrency API
public class ExampleCountDownLatch
{
public void doSomething () throws InterruptedException
{
final CountDownLatch latch = new CountDownLatch(1);
Thread thread = new Thread()
{
public void run ()
{
System.out.println("do something");
latch.countDown();
}
};
System.out.println("waiting for execution of method in your example class");
thread.start();
// wait for reasonable time otherwise kill off the process cause it took
// too long.
latch.await(3000, TimeUnit.MILLISECONDS);
// now I can do something from your example 2
System.out.println("now i can execute from example 2 do something else");
}
}
Anyway just another approach if you had an option.
UPDATE:
Here is a blog about this very topic.
Couple of points :
you should acquire lock before calling wait or notify method. The
lock must be on same object. In code you are calling wait on example2
object but calling notify on different object.
thread.run() means calling run method of thread object, its not
creating new thread its same as example.doSomething(). When you
create thread start that thread by calling start method.
Here is my implementation
class Example implements Runnable
{
public void run()
{
doSomething();
}
public void doSomething(){
synchronized(this){
System.out.println("Do something else");
try{
Thread.sleep(1000);
this.notify();
}catch (InterruptedException ignore) {}
}
}
}
class Example2 implements Runnable
{
Thread thread;
Example example;
public Example2(Example example){
this.example = example;
}
public void run(){
doSomething();
}
public void doSomething(){
synchronized(example){
System.out.println("waiting for example 1 to complete");
try{
example.wait();
}catch (InterruptedException ignore) {}
}
System.out.println("Do something");
}
}
public class Entry{
public static void main(String[] args){
Example example = new Example();
Example2 obj = new Example2(example);
Thread t = new Thread(obj);
t.start();
Thread t2 = new Thread(example);
t2.start();
}
}
In code Thread.sleep(1000); statement is not needed.
Here is one more implementation using join method
class Example implements Runnable
{
public void run()
{
doSomething();
}
public void doSomething(){
System.out.println("Do something else");
try{
Thread.sleep(1000);
}catch (InterruptedException ignore) {}
}
}
class Example2 implements Runnable
{
Thread thread;
Example example;
public Example2(Example example){
this.example = example;
}
public void run(){
System.out.println("waiting for example 1 to complete");
Thread t = new Thread(example);
try{
t.start();
t.join();
}catch(InterruptedException ie){
}
doSomething();
}
public void doSomething(){
System.out.println("Do something");
}
}
public class Entry{
public static void main(String[] args){
Example example = new Example();
Example2 obj = new Example2(example);
Thread t = new Thread(obj);
t.start();
}
}