I have searched a lot but not able to find particular solution. There are also some question regarding this on stackoverflow but i am not able to find satisfactory answer so i am asking it again.
I have a class as follow in java . I know how to use threads in java.
//please do not consider syntax if there is printing mistake, as i am typing code just for showing the concept in my mind
public class myclass{
private List<String> mylist=new ArrayList<String>();
public addString(String str){
//code to add string in list
}
public deleteString(String str){//or passing an index to delete
//code to delete string in list
}
}
now i want to do these two operations simultaneously. for that i have created two thread class one performs addString() logic in run and another perform deleteString() logic.i am passing mylist in the constructor of each thread but how can i return an object after performing addition and deletion to mylist?
Before i was thinking that "If i am passing the mylist in constructor of thread it passes the address of the mylist to thread and thread performs operations on it that changes refer to mylist object" But it is not like that as the changes are not reflacted to mylist object . can any one elaborate this?
what is the best way to achieve this?
the requirement is like that if a thread is inserting an element at last another thread should be able to delete some element at other index say 2nd simultaneously.
EDIT
i have done it as follow: thanx to Enno Shioji
public class myClass {
private List<String> mylist = Collections.synchronizedList(new ArrayList<String>());
public myClass(){
mylist.add("abc");
mylist.add("def");
mylist.add("ghi");
mylist.add("jkl");
}
public void addString(String str) {
mylist.add(str);
}
public void displayValues() {
for (int i = 0; i < mylist.size(); i++) {
System.out.println("value is " + mylist.get(i) + "at " + i);
}
}
public void deleteString(int i) {
mylist.remove(i);
}
}
class addThread {
public static void main(String a[]) {
final myClass mine = new myClass();
Thread t1 = new Thread() {
#Override
public void run() {
mine.displayValues();
mine.addString("aaa");
mine.displayValues();
}
};
Thread t2 = new Thread() {
public void run() {
mine.displayValues();
mine.deleteString(1);
mine.displayValues();
}
};
t1.start();
t2.start();
}
}
is there any other way to do so?
Use Synchronized List , It would be thread safe
Use Collection.synchronizedList(yourPlainList)
Threads and object instance are different concepts. If you want to share data among threads, you need to access a single object instance from two threads. In this case, you should do something like this.
public class MyClass{
private final List<String> mylist = new ArrayList<String>();
public synchronized void addString(String str){
//code to add string in list
}
public synchronized void deleteString(String str){
//or passing an index to delete
//code to delete string in list
}
}
and then
final MyClass mine = new MyClass();
Thread t1 = new Thread(){
public void run(){
mine.addString("aaa");
}
}();
Thread t2 = new Thread(){
public void run(){
mine.deleteString("bbb");
}
}();
t1.start();
t2.start();
Note how you are referring to the same object instance (mine) from both threads. Also note that I added the synchronized keyword to make MyClass thread-safe. This forces all operations to be done sequentially rather than truly "simultaneously". If you want true simultaneous operations on the collection, you will need to use concurrent data structures like a Skip List and get rid of synchronized keyword.
Related
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
My code basically goes like this:
//in Main Thread: (myList is a volatile field)
myList = new ArrayList<myClass>();
Thread myThread = new Thread(new MyCustomRunnable(myList));
myThread.start();
//some lines of code NOT involving myList
myThread.join();
//myList appears empty here even though I can see that the list has been populated
//in the other thread
Is there a reason for this behavior? Like I said, i can see in the debugger that the list has been populated in the called thread, but these changes don't appear in the caller thread after the join() method. MyCustomRunnable also declares the ArrayList as a volatile field, assigned by the constructor.
UPDATE:
Ok, I made a simpler program, replacing the ArrayList with a simple Integer and the results are the same...
public class Threading {
private volatile static Integer i = 0;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new MyCustomRunnable(i));
t.start();
t.join();
System.out.println(i); //prints '0', I expected '1'
}
}
public class MyCustomRunnable implements Runnable {
private volatile Integer i;
public MyCustomRunnable(Integer i) {
this.i = i;
}
public void run() {
this.i = 1;
}
}
Why isn't the Integer's value updated in the main Thread?
Add
public static void setI(int i) {
Threading.i = i;
}
to your Threading class and in your runnable add
public void run() {
this.i = 1;
Threading.setI(1);
}
This has nothing to do with multithreading, just variable scoping. i in the Threading class is not updated in MyCustomRunnable's run method.
Question:
Suppose we pass a ArrayList to Runnable constructor. In the Runnable class we add certain strings to the list. Now we run the Thread from main() and wait for its completion. After the Thread execution is over, is it possible that when we iterate the list in main() we get the strings(values) added to the list by the Runnable class because the reference to the Arraylist is created in Heap.
but when I iterate the list, it is empty. Could anyone explain why the list is empty.
Thanks in Advance:
Vijay K
public class GetListThread implements Runnable{
private List<String> names;
public GetListThread(List<String> names) {
super();
this.names = names;
}
#Override
public void run() {
for(int i=0;i<4;i++){
try {
names.add(ThreadLocalRandom.current().nextInt(1,10) + "A");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//System.out.println(names);
}
}
public class TestThread {
public static void main(String[] args) {
List<String> names = new ArrayList<String>();
GetListThread g = new GetListThread(names);
Thread t = new Thread(g);
t.start();
System.out.println(t.getState());
for(String s : names){
System.out.println(s);
}
}
}
After the Thread execution is over, is it possible that when we iterate the list in main() we get the strings(values)
Yes, the collection is not thread safe, there is no guarantee you will ever see anything. You might even see null values i.e. where the size is correct but the elements are not.
Could anyone explain why the list is empty.
However in you case, you are not waiting, so there is almost no chance it will have all its elements.
The thread takes time to start, so it is highly unlikely you will even see the first element added.
I have this small sample of code, while modifying the list, i lock it with synchronized, but while reading the list it comes to ConcurrentModificationException, because without "synchronized" the lock has no effect. Is it possible to lock an object for all threads which use the object, even the un-synchronized, too?
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
public static void main(String[] args) {
final Random r = new Random(System.currentTimeMillis());
List<Integer> list = new ArrayList<>();
new Thread(new Runnable() {
public void run() {
while (true) {
synchronized (list) {
list.add(r.nextInt());
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
for (Integer i : list) {
System.out.println(i);
}
}
}
}).start();
}
}
the backgorund is that i dont want to change all pieces in my code which read the object
You might consider using a concurrent implementation of List, instead of ArrayList. Perhaps a CopyOnWriteArrayList.
final List<Integer> list = new CopyOnWriteArrayList<Integer>();
Is it possible to lock an object for all threads which use the object.
In a word, No. When one thread enters a synchronized(foo) {...} block, that does not prevent other threads from accessing or modifying foo. The only thing it prevents is, it prevents other threads from synchronizing on the same object at the same time.
What you can do, is you can create your own class that encapsulates both the lock and the data that the lock protects.
class MyLockedList {
private final Object lock = new Object();
private final List<Integer> theList = new ArrayList<>();
void add(int i) {
synchronized(lock) {
theList.add(i);
}
}
void printAll() {
synchronized(lock) {
for (Integer i : theList) {
System.out.println(... i ...);
}
}
}
...
}
If you can modify the function which concurrently uses the object, just add synchronized in every critical section:
while (true) {
synchronized(list){
for (Integer i : list) {
System.out.println(i);
}
}
}
if you can't , create a specified lock that is responsible for locking the threads:
Lock lock = new Lock();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
new Thread(new Runnable(){
//...
synchronized(lock){
do unsynchonized function on list
}
//...
}).start();
the latter may slow down the process if one of the functions already doing some locking, but in this way you can ensure you always synchronize the access to concurrent objects.
Hi i have made a something that extends thread that adds adds an object that has a IP in it. then i made two instances of this thread and started them. they use the same list.
I now want to use Synchronized to stop the concurrent update problem. But its not working and i cant work out why.
My main class:
import java.util.*;
import java.io.*;
import java.net.*;
class ListTest2 {
public static LinkedList<Peer> myList = new LinkedList<Peer>();
public static void main(String [] args) {
try {
AddIp test1 = new AddIp(myList);
AddIp test2 = new AddIp(myList);
test1.start();
test2.start();
} catch(Exception e) {
System.out.println("not working");
}
}
}
My thread class:
class AddIp extends Thread {
public static int startIp = 0;
List<Peer> myList;
public AddIp(List<Peer> l) {
myList = l;
}
public synchronized void run() {
try {
startIp = startIp+50;
int ip = startIp;
InetAddress address = InetAddress.getByName("127.0.0.0");
Peer peer = new Peer(address);
while(ip <startIp+50) {
ip++;
address = InetAddress.getByName("127.0.0."+ip);
peer = new Peer(address);
myList.add(peer);
if(myList.indexOf(peer)== (myList.size() -1)) {
} else {
System.out.println("Lost"+peer.peerIp);
}
}
} catch(Exception e) {
}
}
}
Can anyone help me out here im lost for ideas thanks.
public synchronized void run()
Synchronizes on calling instance: this.
So,
1st thread synchronizes on test1 and 2nd thread synchronizes on test2, which doesn't help at all.
You want to synchronize on the shared resource, in this case: myList
public void run() {
synchronize(myList){
//your Logic
}
}
As a side note: Implement runnable instead of extending a Thread. Read more here.
You'd be better off implementing Runnable oppose to extending thread
also
public void run() {
synchronize(list){
//stuffs
}
}
they use the same list.
You can try to use Vector instead List. Vector is synchronized
or set your List to be synchronized:
List myList = Collections.synchronizedList(myList);
instead to use:
synchronize(myList){
}
The easiest way is to use a List implementation that can handle multiple threads. Try CopyOnWriteArrayList.