I am trying to learn multithreading concepts in Java. I am stuck with error during execution of my code snippet.
My code snippet:
class ThreadDemo {
public static void main(String args[]) {
try{
int [] arr = new int[10] ;
for(int i = 0 ; i < 10 ; i++)
arr[i] = i ;
for(int c =0 ; c < 2 ; c++){
for(int i = 0 ; i < 3 ; i++) //I want to run it on one thread
System.out.println(arr[i]);
for(int j = 0 ; j < 5 ; j++) //I want to run it on another thread
System.out.println(arr[j]);
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
Now, to solve this I have tried,
class ThreadDemo {
public static void main(String args[]) {
try{
int [] arr = new int[10] ;
for(int i = 0 ; i < 10 ; i++)
arr[i] = i ;
for(int c =0 ; c < 2 ; c++){
Thread thread1 = new Thread () {
public void run () {
for(int i = 0 ; i < 3 ; i++) //I want to run it on one thread
System.out.println(arr[i]);}
};
Thread thread2 = new Thread () {
public void run () {
for(int j = 0 ; j < 5 ; j++) //I want to run it on one thread
System.out.println(arr[j]);}
};
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
But gives error. Can anyone help me how to solve this ?
In
for (int c = 0; c < 2; c++) {
Thread thread1 = new Thread() {//<- here
you are creating anonymous inner class that extends Thread class. You must know, that anonymous inner classes have access only to final local variables of method that they are created so if you want to gain access to int [] arr you must make it final like
final int[] arr = new int[10];
Also you created threads but you didn't start them. To do that invoke their start() method like thread1.start().
If you don't want to declare local variables of method as final you should consider creating threads not as anonymous inner classes but as separate classes for example
class MyThread extends Thread {
int[] array;
int iterations;
public MyThread(int[] arr, int i) {
array=arr;
iterations = i;
}
#Override
public void run() {
for (int i = 0; i < iterations; i++)
System.out.println(array[i]);
}
}
class ThreadDemo {
public static void main(String args[]) {
try {
int[] arr = new int[10];
for (int i = 0; i < 10; i++)
arr[i] = i;
for (int c = 0; c < 2; c++) {
MyThread thread1 = new MyThread(arr, 3);
MyThread thread2 = new MyThread(arr, 5);
thread1.start();
thread2.start();
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
FYI: Extending Thread is not the best idea if you're not actually providing any additional logic to it. It's best to use a Runnable and pass it to the threads constructor.
Thread t = new Thread(new Runnable() {
public void run() {
}
});
t.start();
Aside from that, as someone else noted, any variables directly in an anonymous class need to be declared as final.
Related
when I was reading about different ways of defining threads in Java, I can't able to synchronize Thread as a nested class. This is the code.
class OuterClass {
int count = 0;
InnerClass in[];
OuterClass() {
in = new InnerClass[4];
for (int i = 0; i < 4; i++) {
in[i] = new InnerClass();
}
}
public void startFun() throws Exception{
for (int i = 0; i < 4; i++) {
in[i].start();
}
for (int i = 0; i < 4; i++)
in[i].join();
}
public static void main(String[] agrs) throws Exception {
OuterClass oc = new OuterClass();
oc.startFun();
}
class InnerClass extends Thread {
public synchronized void run() {
count ++;
System.out.println(count);
}
}}
How to synchronize count variable in this program by using thread as a nested class? Because I used this model in my project. Output for the above program was:
output:
1
4
3
2
How to synchronize and get the output as:
1
2
3
4
You have 4 different objects (and 4 different monitors for locking) for synchronization (InnerClass1, InnerClass2 etc). For synchronization of all your threads, you should use one object (one monitor) for example:
class OuterClass {
Object ob = new Object();
volatile int count = 0;
InnerClass in[];
OuterClass() {
in = new InnerClass[4];
for (int i = 0; i < 4; i++) {
in[i] = new InnerClass();
}
}
public void startFun() throws Exception{
for (int i = 0; i < 4; i++) {
in[i].start();
}
for (int i = 0; i < 4; i++)
in[i].join();
}
public static void main(String[] agrs) throws Exception {
OuterClass oc = new OuterClass();
oc.startFun();
}
class InnerClass extends Thread {
public void run() {
synchronized (ob){
count ++;
System.out.println(count);
}
}
}}
also, your shared field should be volatile.
Having trouble printing the contents of my array in a non synchronized way. I am looking to iterate through and output the letters "A" , "B" , "C" in a non sequential manner from a static array of strings using Threads to print the loop.
Here is my code:
public class ThreadWithExtends extends Thread {
public ThreadWithExtends() {
super();
}
public void run() {
String[] arr = { "A", "B", "C" };
int num = 10;
try {
for (int j = 0; j < num; j++) {
for (int i = 0; i < arr.length; i++) {
sleep((int) (Math.random() * 1000));
System.out.print(arr[i] + " ");
}
}
} catch (InterruptedException e) {
System.out.println("Finished");
}
}
}
My TestThread class:
public class TestThread {
public static void main(String args[]) {
new ThreadWithExtends().start();
}
}
My Output : A B C A B C A B C A B C A B C A B C A B C A B C A B C A B C
My Desired Output : C A B A B C B A C .. etc , not sequential like above.
Actually you aren't executing any code in parallel. You only created one thread that prints some statements sequentially. You need to create three threads that print stuff on their own, like so:
public class Printer extends Thread {
private String mText;
public Printer(String text) {
mText = text;
}
#Override
public void run() {
int num = 1_000;
for (int i = 0; i < num; i++) {
System.out.print(mText + " ");
}
}
}
and then
public static void main(String args[]) {
new Printer("A").start();
new Printer("B").start();
new Printer("C").start();
}
Now you have three threads that run in parallel. Prints should be mixed now.
Note that in general you shouldn't care about how the scheduler schedules the threads. It tries to optimize and it works well. It probably has its reasons why it scheduled this or that way. You can assign priorities to threads if you want to tell the scheduler your preferences.
I am trying to learn using the monitor by creating an array of int, length being 100. It is filled with 0 and I try to make 4 threads that would swap the 0 with numbers from top and bottom of the array.
For some reason only 2 out of 4 threads (and it seems that it is random) executes. I have tried to change it by creating an array and increasing the respected member of the array by 1 for 100k iterations and it seems that every thread did it for about 25k times so I suppose the problem is with the part where I tried to swap 0 in the array.
Here is my code:
class addFromBottom implements Runnable{
int number;
public addFromBottom(int number){
this.number=number;
}
#Override
public void run() {
for (int i = number-1; i <100 ; i+=2) {
if (MainClass.testMonitor.elementsNotChanged>0)
MainClass.testMonitor.addNumberFromBottom(number,i);
else
break;
}/*
while (MainClass.testMonitor.testCounter>0)
MainClass.testMonitor.testCounter(number);*/
}
}
class addFromTop implements Runnable{
int number;
public addFromTop(int number){
this.number=number;
}
#Override
public void run() {
for (int i = 95+number; i >=0 ; i-=2) {
if (MainClass.testMonitor.elementsNotChanged>0){
MainClass.testMonitor.addNumberFromBottom(number,i);
}
else {
break;
}
}
/*while (MainClass.testMonitor.testCounter>0)
MainClass.testMonitor.testCounter(number);*/
}
}
class monitor
{
int elementsNotChanged = 100;
int[] array;
int testCounter = 100000;
int[] testArray = new int[]{0,0,0,0};
public monitor(){
array=new int[100];
for (int i = 0; i < 100; i++) {
array[i]=0;
}
}
synchronized void addNumberFromBottom(int number,int index){
if (elementsNotChanged<=0) {
return;
}
if (array[index]==0){
array[index]=number;
return;
}
}
//for testing if the threads are working seperatly
synchronized void testCounter(int number) {
if (testCounter<=0)
return;
testArray[number - 1]++;
testCounter--;
notifyAll();
}
}
class MainClass {
public static int a=0;
public static volatile monitor testMonitor;
public static void main(String[] args) throws InterruptedException {
testMonitor = new monitor();
Thread thread = new Thread(new addFromBottom(1));
Thread thread2 = new Thread(new addFromBottom(2));
Thread thread3 = new Thread(new addFromTop(3));
Thread thread4 = new Thread(new addFromTop(4));
thread.start();
thread2.start();
thread3.start();
thread4.start();
thread.join();
thread2.join();
thread3.join();
thread4.join();
System.out.println();
System.out.println();
System.out.println();
System.out.println("value: i");
for (int i = 0; i < 100; i++) {
System.out.println(testMonitor.array[i]+" "+i);
}
//for testing with the array of 4 elements if all threads are doing their work
int sum=0;
for (int i = 0; i <4 ; i++) {
//System.out.println(testMonitor.testArray[i]);
sum+=testMonitor.testArray[i];
}
// System.out.println(sum);
}
}
Why is value set correctly even though we use different locks in different threads?
public class MyThread implements Runnable {
static String a = "LOCK";
static String b = "LOCK";
int id;
static int value = 0;
MyThread(int id) {
this.id = id;
}
#Override
public void run() {
if (id == 0) {
synchronized (a) {
for (int i = 0; i < Main.N; i++)
value = value + 3;
}
} else {
synchronized (b) {
for (int i = 0; i < Main.N; i++)
value = value + 3;
}
}
}
}
public class Main {
static final int N = 100000;
static int ITER = 100;
public static void main(String[] args) {
Thread threads[] = new Thread[2];
boolean sw = true;
for (int j = 0; j < ITER; j++) {
MyThread.value = 0;
for (int i = 0; i < 2; i++)
threads[i] = new Thread(new MyThread(i));
for (int i = 0; i < 2; i++)
threads[i].start();
for (int i = 0; i < 2; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (MyThread.value != 2 * 3 * N) {
System.out.println("i was different than " + 2 * 3 * N + ", it is " + MyThread.value);
sw = false;
}
}
if (sw)
System.out.println("Something is strange");
}
}
Java string literals are interned to save memory.
Your two "LOCK" strings (and therefore the two objects you lock on) are actually the same object.
This is (one of the reasons) why you should never lock on primitives.
Never use String as locks as there may well be the same instance of an other String because of the string pool.
In your case, your two "LOCK" strings are actually the same object.
In Java, there are 3 threads that want to access (read-only) an immutable hashmap to do something. Is SynchronizedMap class below the fastest solution for that purpose? If not, then what would be faster to use?
import com.carrotsearch.hppc.IntObjectMap;
import com.carrotsearch.hppc.IntObjectOpenHashMap;
public class abc {
public static void main(String[] args) {
final IntObjectMap<int[]> map = new IntObjectOpenHashMap<int[]>();
for (int i = 0; i < 4; i++) {
map.put(i, new int[] {1, 2, 3, 4, 5});
}
Thread[] threads = new Thread[3];
class SynchronizedMap {
private final Object syncObject = new Object();
public final int[] read(int i) {
final int[] value;
synchronized (syncObject) {
// code that reads-only immutable map object
value = map.get(i);
}
return value;
}
}
final SynchronizedMap syncMap = new SynchronizedMap();
class AccessMap implements Runnable {
private int id;
AccessMap(int index) { id = index; }
public void run() {
// code that reads-only immutable map object like this:
for (int i = 0; i < 4; i++) {
final int[] array = syncMap.read(i);
for (int j = 0; j < array.length; j++)
System.out.println(id + ": " + array[j] + " ");
}
}
}
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new AccessMap(i) {});
threads[i].start();
}
for (int i = 0; i < threads.length; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Is SynchronizedMap class below the fastest solution for that purpose?
No. If the HashMap is truly immutable/read-only then a volatile Map<...> is the way to go.
volatile IntObjectMap<int[]> readOnlyMap = new IntObjectOpenHashMap<int[]>();
If you are starting your threads after your map is built then you don't even need the volatile. The only time you would need the volatile is if you are swapping in a new map that is being accessed by currently running threads.
final IntObjectMap<int[]> readOnlyMap = new IntObjectOpenHashMap<int[]>();