Java multi-threads programming - java

I am a beginner of Java programming learner. I can't know how to correct the following Java program. Kindly help to let me know how to correct it. Thanks a lot.
public class TMA1Q2 {
public static void main(String[] args) {
System.out.println("Usage: java TMA1Q2 {number of Threads}");
// Create tasks
Runnable taskA = new PrintTwoConcurThreads("Thread A ");
Runnable taskB = new PrintTwoConcurThreads(" Thread B ");
// Create threads
Thread thread1 = new Thread(taskA);
Thread thread2 = new Thread(taskB);
// Start threads
thread1.start();
thread2.start();
}
}
// The task that implements Runnable
class PrintTwoConcurThreads implements Runnable {
private final String TwoConcurThreads;
private String[] args;
public PrintTwoConcurThreads(String numThreads) {
TwoConcurThreads = numThreads;
}
// Override the run() method
#Override
public void run() {
// Print the value input argument times
int numThreads = Integer.parseInt(args[0]);
Thread[] myThread;
myThread = new Thread[numThreads];
for (int i = 0; i < numThreads; i++) {
System.out.println(TwoConcurThreads + i);
}
}
}

private String[] args;
This args field is never initialized, so it will be having a default value of null.
When you try to access it in following line you get a NullPointerException
int numThreads = Integer.parseInt(args[0]);
It is not clear what you're trying to do. Atleast this would help you to see what's going wrong.
Also I have no Idea why following lines are used, You create Thread[] but never you used it.
Thread[] myThread;
myThread = new Thread[numThreads];

Related

threading using extend Thread

I can get my method threadR to run by a runnable thread, however i cant seem to get threadL to run as a thread and print out to the console
System.out.println("Greetings from Fred! threadL"); from my run thread
What am i doing wrong?
package threads;
import java.util.ArrayList;
import java.util.List;
public class Threads extends Thread implements Runnable {
private final List<Thread> threadList = new ArrayList<>();
private String e,l;
private Thread greetings;
public static void main(String[] args) {
String[] elements = {"Tim","Fred"};
Threads t = new Threads();
for (String e: elements) {
t.threadL(e);
t.threadR(e);
}
for(int index = 0;index<t.threadList.size();index++){
System.out.print(t.threadList.get(index).getName()+ " ID "+ t.threadList.get(index).getId()+"\n");
}
}
public List<Thread> threadL(String l) {
Thread greetings1 = new Thread(l);
greetings1.start();
threadList.add(greetings1);
//System.out.print(greetings.getName()+"\n");
//System.out.print(greetings.getId()+"\n");
return(threadList);
}
public List<Thread> threadR(String f) {
greetings = new Thread(f);
Thread greetingsFromFred = new Thread(greetings) {
#Override
public void run() {
System.out.println("Greetings from Fred! threadR");
}
}; greetingsFromFred.start();
threadList.add(greetings);
//System.out.print(greetings.getName()+"\n");
//System.out.print(greetings.getId()+"\n");
return(threadList);
}
public void run() {
System.out.println("Greetings from Fred! threadL"); //this is what wont run
}
When you pass a String as the only argument to new Thread(String); you are actually setting the Thread name. You probably meant to pass a Runnable to the Thread as such
Thread greetings1 = new Thread(this);
Thread Constructors

Synchronized method does not work as expected

I have a variable which is shared by two threads. The two threads will do some operations on it. I don't know why the result of sharedVar is different every time I execute the program.
public class Main
{
public static int sharedVar = 0;
public static void main(String[] args)
{
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
mt1.start();
mt2.start();
try
{
// wait for the threads
mt1.join();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(sharedInt); // I expect this value to be 20000, but it's not
}
}
The following is the class "MyThread"
public class MyThread extends Thread
{
private int times = 10000;
private synchronized void addOne()
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
#Override
public void run()
{
addOne();
}
}
The final result of sharedVar sometimes are 13735, 12508, or 18793; but never 20000, which is the result I expect. Another interesting thing about the program is when times=1000. I always get 2000 as the final result.
Can anyone explain this phenomenon?
A synchronized method protects the resource this that means that your code is equivalent to:
private void addOne()
{
synchronized(this)
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
}
But you have 2 objects for which addOne method is called. That means this for mt1.addOne is not the same than this for mt2.addOne and therefore you don't have a common resource of synchronization.
Try changing yout addOne code to:
private void addOne()
{
synchronized(MyThread.class)
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar ++;
}
}
}
And you will observe the expected behaviour. As the comments below suggest, it is better to use a different object than MyThread.class for synchronization since class objects are accesible from many points and it is easy that other code may try to synchronize using the same object.
When you use synchronized on non-static method, you use current object as monitor.
When you use synchronized on static method, you use current object of class (ClassName.class static field) as monitor.
In your case, you use synchronized on Thread's object (2 different instances), so two different threads will modify your sharedVar static field at same time.
You can fix it in different ways.
Move addOne method to Main and make it static.
private static synchronized void addOne(int times)
{
for (int i = 0; i < times; ++i)
{
sharedVar++;
}
}
Or you can create class called SharedVar with field private int var; and method synchronized void addOne(int times) and pass single instance of SharedVar to your treads.
public static void main(String[] args)
{
SharedVar var = new SharedVar();
MyThread mt1 = new MyThread(var);
MyThread mt2 = new MyThread(var);
mt1.start();
mt2.start();
try
{
// wait for the threads
mt1.join();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(var.getVar()); // I expect this value to be 20000, but it's not
}
But if you need only one integer to be changed in multiple threads, you can use classes from java.til.concurrent.*, like AtomicLong or AtomicInteger.
Define sharedVar as an AtomicLong instead of int. Making the function synchronized works as well but it is less efficient because you only need the increment to be synchronized.
When a thread is about to execute a 'synchronized' instance method, it aqcuires the lock on the Object(to be precise, lock on that object monitor).
So in your case, Thread mt1 acquires lock on Object mt1 and Thread mt2 acquires lock on Object mt2 and they do not block each Other as the two threads are working on two different locks.
And when two threads modify a shared variable concurrently(not synchronized way), the result is unpredictable.
Well about the case of value 1000, for smaller inputs the interleaved execution might have resulted in correct result(luckily).
Sol : remove the synchronized keyword from addOne method and make sharedVal as type of 'AtomicInteger'
Join the thread immediately after start method. From this thread-1 will start and go to dead state after that thread-2 will start and go to dead state. So it will print your expected output always.
Change the code as shown below:-
public class Main{
public static int sharedVar = 0;
public static void main(String[] args)
{
MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();
try
{
mt1.start();
mt1.join();
mt2.start();
mt2.join();
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
System.out.println(sharedVar);
}
}
class MyThread extends Thread
{
private int times = 1000000;
private synchronized void addOne()
{
for (int i = 0; i < times; ++i)
{
Main.sharedVar++;
}
}
#Override
public void run()
{
addOne();
}
}

Synchronized two threads not working synchronized

consider the following code:
public class Main {
public static void main(String[] args){
MyObject obj = new MyObject();
Thread1 t1 = new Thread1(100,'#',obj);
Thread1 t2 = new Thread1(100,'*',obj);
t1.start();
t2.start();
}
}
public class Thread1 extends Thread {
int myNum;
char myChar;
MyObject myObj;
public Thread1(int num, char c, MyObject obj){
myNum = num;
myChar = c;
myObj = obj;
}
public synchronized void run(){
for(int i = 1; i<myNum; i++){
if((i%10)==0)
System.out.println("");
System.out.print(myChar);
}
}
}
The class MyObject is empty class without anything spacial.
My question is, why the synchronized is not working and I get printed the '#' and '' simultaneously and in random order and not one after the other?
Synchronization locks the monitor of an object. In your case, you are synchronizing against each of the threads objects, that is Thread A locks against Threads A's monitor and Thread B locks against Thread B's monitor. Thus they are not interacting.
I think that you meant the following for the run() method:
public void run(){
synchronized (myObj) {
for(int i = 1; i<myNum; i++){
if((i%10)==0)
System.out.println("");
System.out.print(myChar);
}
}
}
If that was indeed your intended use for myObj, then I would suggest the following change too; as it will help make the code more readable.
Change:
MyObject myObj;
to:
private final MyObject lock;
EDIT an alternative approach, that does not lock against myObj but instead the Thread1's instance of Class.
public void run(){
doJob();
}
private static synchronized void doJob() {
for(int i = 1; i<myNum; i++){
if((i%10)==0)
System.out.println("");
System.out.print(myChar);
}
}
You can try to put thread.join(), wait for first thread in execution finished to start next one
public class hilos {
public static void main(String[] args) throws InterruptedException{
MyObject obj = new MyObject();
Thread1 t1 = new Thread1(50,'#',obj);
Thread1 t2 = new Thread1(50,'*',obj);
Thread[] threads = {t1, t2};
start(threads);
}
public synchronized static void start(Thread[] threads) throws InterruptedException{
synchronized(threads){
for(int i=0; i < threads.length; i++) {
threads[i].start();
threads[i].join();
}
}
}
}
OUTPUT:
#########
##########
##########
##########
##########*********
**********
**********
**********
**********

How to print numbers side by side on the same line using different threads in java?

This is what the output should look like:
Each column should be printed using a separate thread. So in this case there will be 3 threads, one that prints the numbers, an other that prints their squares and an other that prints their cubes.
Following everyone's comments i have written this code.
public class PrintThread
{
private static final int LIMIT=10;
final static Queue<Integer> number=new LinkedList();
final static Queue<Integer> square=new LinkedList();
final static Queue<Integer> cube=new LinkedList();
public static void main(String[] args)
{
System.out.println("Number\tSquare\tCube");
for(int i=0;i<LIMIT;i++)
number.offer(i);
new Thread(new Runnable(){
public void run(){
for(int i=0;i<LIMIT;i++)
square.offer(i*i);
}
}).start();
new Thread(new Runnable(){
public void run(){
for(int i=0;i<LIMIT;i++)
cube.offer(i*i*i);
}
}).start();
for(int i=0;i<LIMIT;i++){
System.out.println(number.poll()+"\t"+square.poll()+"\t"+cube.poll());
}
}
}
Now this still does not ensure the correct output.
I want the main thread to print only after the other two threads have finished filling the queues. How do I do that?
Actually 3 thread printing on the same line one after another conveys the meaning of sequential execution. I do not think threads are useful here.
But if you mean only Calculation needs to be done using different threads, then you can use join() on the threads. You can use one loop to initialize and start the threads and in the second loop join() them. (Note that if you join() in the same loop, then the threads execute as sequentially.)
After the second loop you can print the formatted result.
Try This :
class RunnableDemo implements Runnable {
private Thread t;
private String threadName;
static int i=0;
RunnableDemo( String name){
threadName = name;
}
public void run() {
i=i+1;
System.out.print(""+i+"\t\t"+(i*i)+"\t");
}
public void start ()
{
System.out.print("\t"+(i*i*i+"\n"));
}
}
class TestThread {
public static void main(String args[])
{
System.out.print("Number Square Cube\n");
RunnableDemo [] r1=new RunnableDemo[10];
for(int i=1;i<10;i++)
{
r1[i]=new RunnableDemo(""+i);
r1[i].run();
r1[i].start();
}
}
}

Passing parameter to Java Thread

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

Categories

Resources