Basically I have an integer array which i want to hand over to a thread, but i can't get the syntax right.
// Create list
List <Integer> list = new ArrayList<Integer>();
// Create thread
TPServer server = new TPServer(port, <Integer> list);
new Thread(server).start();
// Below is the TPServer class
// TPServer Class
public class TPServer implements Runnable {
private List <Integer> list = null;
private int port = 0;
private boolean isStopped = false;
public TPServer(int port, List <Integer> list) {
this.list = list;
this.port = port;
}
}
You haven't implemented Runnable and also it should be new TPServer(port, list);
You pass a generic argument the same as any other.
TPServer server = new TPServer(port, list);
You might wanna use a list that uses a semaphore to prevent concurent access Or use a list type that is thread safe, if your list is being used also out of the thread. (and if it is used only inside the thread, create it inside obviously :=) )
Related
I need to maintain a list of InetSocketAdress objects. I have a ConcurrentLinkedQueue that contains these objects, I do not want to remove objects from the queue but I need to know where I am in the queue. I have a solution but for some reason I'm thinking there must be a better way.
private static final ConcurrentLinkedQueue<InetSocketAddress> allSocketAddrs
= new ConcurrentLinkedQueue();
public List<InetSocketAddress> activeSocketAddrs = new ArrayList();
private Integer queuePos = 0;
public void addInetSocketAddr(InetSocketAddress isa){
if(!allSocketAddrs.contains(isa)){
allSocketAddrs.add(isa);
}
}
private void getNewInetSokcetAddrs(){
Object[] newAddrs = allSocketAddrs.toArray();
for(int x = queuePos;x<newAddrs.length;x++){
InetSocketAddress isa = (InetSocketAddress)newAddrs[x];
//items added to this list CAN/WILL be removed.
activeSocketAddrs.add(isa);
queuePos++;
}
I'd separate the "all" collection and the new items as follows. It's a bit ugly to add an element to a different collection in computeIfAbsent(), but this way you can easily and efficiently get new items.
Example uses LinkedBlockingQueue because ConcurrentLinkedQueue doesn't have drainTo. The getAllNew() method also works differently (a bulk get of new elements), since you don't need to actively update the active list. If you want to handle the elements one by one, you could provide directt access to the queue.
private static final Map<InetSocketAddress, Object> allSocketAddrs = new ConcurrentHashMap<>();
private static final LinkedBlockingQueue<InetSocketAddress> activeSocketAddrs = new LinkedBlockingQueue<>();
private final static Object DUMMY = new Object();
public void addInetSocketAddr(InetSocketAddress isa){
allSocketAddrs.computeIfAbsent(isa, key -> {
activeSocketAddrs.add(key);
return DUMMY;
}
}
private List<InetSocketAddress> getAllNew() {
List<InetSocketAddress> list = new ArrayList<>();
activeSocketAddrs.drainTo(list);
return list;
}
// Different threads could use this to get the queue and do a blocking
// take() for example
private Queue<InetSocketAddress> getNewQueue() {
return activeSocketAddrs;
}
I have the following class:
public class MyClass{
private List<Integer> ints = new LinkedList<Integer>();
public List<Integer> getInts(){
return ints;
}
public synchronized void doAction(){
//Do some with the list
}
}
I need to allow only one thread at the time having acces to the List. I would do that as follows:
public class MyClass{
private List<Integer> ints = new LinkedList<Integer>();
private static final Semaphore s = new Semaphore(1);
public List<Integer> getInts(){
s.acquire();
return ints;
}
public void release(){
s.release();
}
public synchronized void doAction(){
s.acquire();
//Do some with the list
s.release();
}
}
But the implementaion is obviously not reliable, because if the client request the List through the getter for adding some elements into it and forget to call release() we'll get into troubles if try to invoke the doAction method.
What is the solution for the problem?
Don't allow the client to get the reference. Put all the methods that work on the list to MyClass and synchronize them.
You can allow the users to get a snapshot copy of the list however.
You could use a synchronized list:
private List<Integer> ints = Collections.synchronizedList(new LinkedList<Integer>());
I have an ArrayList in Java. Now, I want to access the pointer to the said list. This is so that I can make a variable out of the pointer and make operations using it. Any advise on how to do this?
What I want to do exactly is similar to making "list" below always point to the value of "someOtherList".
import java.util.ArrayList;
import java.util.List;
public class ListContainingObject {
private List list;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public static void main(String args[]){
ListContainingObject listContainingObject= new ListContainingObject();
System.out.println(listContainingObject.getList());
List someOtherList = new ArrayList();
listContainingObject.setList(someOtherList);
System.out.println(listContainingObject.getList());
System.out.println(someOtherList);
someOtherList.add("1");
System.out.println(listContainingObject.getList());
System.out.println(someOtherList);
//I want the two below to have the same value
someOtherList = new ArrayList();
System.out.println(listContainingObject.getList());
System.out.println(someOtherList);
}
}
The seemingly appropriate workaround would be to call the setters again explicitly like below.
public class ListContainingObject {
public void resetList(List toReset) {
this.list = new ArrayList();
toReset = this.list;
}
}
listContainingObject.resetList(someOtherList);
But this would lead to another problem wherein I want solcowiab.getList() and listContainingObject.getList() below to always be the same, assuming that I don't have the source code for SomeOtherListContainingObjectWhichIsABlackBox.
import java.util.ArrayList;
import java.util.List;
public class ListContainingObject {
private List list;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public static void main(String args[]) {
ListContainingObject listContainingObject = new ListContainingObject();
SomeOtherListContainingObjectWhichIsABlackBox solcowiab = new SomeOtherListContainingObjectWhichIsABlackBox();
List aNewList = new ArrayList();
aNewList.add("1");
solcowiab.setList(aNewList);
listContainingObject.setList(solcowiab.getList());
System.out.println(listContainingObject.getList());
System.out.println(solcowiab.getList());
//The two below will have the same value but
//at some point "list" did not point to "someOtherList"
solcowiab.aMethodThatSupposedlyWontCallSetList();
listContainingObject.setList(solcowiab.getList());
System.out.println(listContainingObject.getList());
System.out.println(solcowiab.getList());
}
}
class SomeOtherListContainingObjectWhichIsABlackBox {
private List someOtherList;
public List getList() {
return someOtherList;
}
public void setList(List list) {
this.someOtherList = list;
}
public void aMethodThatSupposedlyWontCallSetList() {
//this one won't be observed by ListContainingObject
setList(new ArrayList());
getList().add("2");
//do some other stuff
//only this assignment will be controlled by ListContainingObject's main method
setList(new ArrayList());
}
}
You can't because the line someOtherList = new ArrayList(); is assigning a whole new "section of memory" to someOtherList, meaning it will point to a different place in memory than listContainingObject.getList().
Now it is true that the listContainingObject has only a reference to your created list, but this reference is not semantically linked to someOtherList. So if someOtherList changes, your object won't know about it.
If you want to clear the lists without destroying the link, use someOtherList.clear() instead.
EDIT: You may be able to get away with resetting the list another way:
public class ListContainingObject {
public void resetList(List toReset) {
this.list = new ArrayList();
toReset = this.list;
}
}
listContainingObject.resetList(someOtherList);
This is, however, a pretty dirty hack. But without somehow manually changing both variables to reference the new structure in memory, I know of no way to get one to automatically update the other.
Probably, you are trying to update the contents of the "list" field.
Please find an solution here:
import java.util.ArrayList;
import java.util.List;
public class ListContainingObject {
private List list;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public static void main(String args[]){
ListContainingObject listContainingObject= new ListContainingObject();
System.out.println(listContainingObject.getList());
List someOtherList = new ArrayList();
listContainingObject.setList(someOtherList);
System.out.println(listContainingObject.getList());
System.out.println(someOtherList);
someOtherList = listContainingObject.getList();
someOtherList.add("1");
System.out.println(listContainingObject.getList());
System.out.println(someOtherList);
//I want the two below to have the same value
//someOtherList = new ArrayList();
someOtherList.clear();
System.out.println(listContainingObject.getList());
System.out.println(someOtherList);
}
}
Thus, someOtherList is referring to the "list" field which is the same.
You have to again setList to the new address as once someOtherList is referring to different. So, as required "list" should be updated also and must be followed elsewhere.
Suppose you have a method, which modifies this list you can achieve this by below.
public void someMethod(){
List someOtherList = getList();
someOtherList = new ArrayList();
//some code
setList(someOtherList);
}
For similar post check: Confused, whether java uses call by value or call by reference when an object reference is passed?
first the someotherlist is pointing to an object in heap
someotherlist ----> Object
then you are making two references to point to the same object in the heap
someotherlist ----
|
Object
|
list -------------
now when you assign the reference someotherlist to a new object in the heap
someotherlist ------> new Object
the object refered by list will not be changed
list -----------> oldobject
you have to call the setters again to make list point to the new object refered by someotherlist
Object (now eligible for garbage collection as referred by none)
someotherobject ------
|
new Object
|
list ------
Note:
you can only refer objects not object references.. what you can do is set up a method for setting the object to someotherlist and assign the same reference to the list also... like
class Test {
List<E> list;
List<E> someOtherList;
setterMethod(ArrayList<E> a) {
someOtherList = a;
list = someOtherList;
}
Edit:
class One {
List<E> list;
public void setList(List<E> newList) {
this.list = newList;
}
//getters and setters and other methods
}
class Two {
One one;
List<E> someOtherList;
public void setSomeOtherList(List<E> newList) {
this.someOtherList = newList;
this.one.setList(newList);
}
//getters and setters and other methods
}
Can anyone tell me why this method is throwing an unchecked or unsafe exception? I understood that to happen when I try to edit the list I am iterating through... in the below, currentAdvanceTactics etc are not being iterated through at all.
public void tacticMeetsRequirements(ArrayList<Tactics> master) {
for (Tactics a : master) {
if (meetsrequirements(a)) {
if (a.movement.equals("Advance")) {
currentAdvanceTactics.add(a);
} else if (a.movement.equals("Retreat")) {
currentRetreatTactics.add(a);
} else if (a.movement.equals("Guard")) {
currentGuardTactics.add(a);
}
}
}
}
This is how the objects used in the master list are created:
for (int b = 0; b < numberoftactics; b++) {
tactic[b] = new Tactics(parsedTactics[b]);
tacticsMaster.add(tactic[b]);
}
parsedTactics is just raw data which gets read into the different variables.
tacticsMaster is declared as such:
public ArrayList<Tactics> tacticsMaster;
then later when I create the object it is contained within:
this.tacticsMaster = new ArrayList<Tactics>();
The currentAdvanceTactics list etc are all created as such:
public ArrayList currentGuardTactics = new ArrayList<Tactics>();
public ArrayList currentAdvanceTactics = new ArrayList<Tactics>();
public ArrayList currentRetreatTactics = new ArrayList<Tactics>();
Thanks in advance for any help!
You are using the raw version of the generic-type (ArrayList<T>). That's why you get the warning.
public ArrayList currentGuardTactics = new ArrayList<Tactics>();
public ArrayList currentAdvanceTactics = new ArrayList<Tactics>();
public ArrayList currentRetreatTactics = new ArrayList<Tactics>();
Try using the parameterized version -
public List<Tactics> currentGuardTactics = new ArrayList<Tactics>();
public List<Tactics> currentAdvanceTactics = new ArrayList<Tactics>();
public List<Tactics> currentRetreatTactics = new ArrayList<Tactics>();
The declaration of your ArrayLists are not type-safe. Change it to:
private ArrayList<Tactics> currentGuardTactics = new ArrayList<Tactics>();
private ArrayList<Tactics> currentAdvanceTactics = new ArrayList<Tactics>();
private ArrayList<Tactics> currentRetreatTactics = new ArrayList<Tactics>()
You should make the members also private. public declarations are usually not the best-practice way.
I have a mulitThread Java application. In one method, there is a need to synchronize a ArrayList. Since arrayList is not a thread safe, so I have to use synchonization. The problem is that object which is type of ArrayList is not a member variable of the object. Prototype of the method is as follows:
public void simultaneousAccess(ArrayListWrapper aListWrapper){
ArrayList list = aListWrapper.getList();
//...Codes manipulate the list
}
Due to mulitthreading, shall I use
A)
public void synchronized simultaneousAccess(ArrayListWrapper aListWrapper){
ArrayList list = aListWrapper.getList();
//...Codes manipulate the list
}
Or
B)
public void simultaneousAccess(ArrayListWrapper aListWrapper){
ArrayList list = aListWrapper.getList();
Synchronized(list){
//...Codes manipulate the list
}
}
From the performance test, neither works.
But I donot know why?
Here comes whole source codes:
package com.juhani.prototype.sync;
import java.util.ArrayList;
public class ArrayListWrapper {
public ArrayList<Integer> aList = new ArrayList<Integer>();
public ArrayListWrapper(){
Integer one = new Integer(1);
Integer two = new Integer(2);
Integer three = new Integer(3);
aList.add(one);
aList.add(two);
aList.add(three);
}
}
package com.juhani.prototype.sync;
import java.util.ArrayList;
public class TestClass {
public int count_test=0;
public synchronized void test(ArrayListWrapper listWrapper){
ArrayList<Integer> list = listWrapper.aList;
int temp = list.get(1)+1;
list.set(1,temp);
}
public void testBlock(ArrayListWrapper listWrapper){
ArrayList<Integer> list = listWrapper.aList;
synchronized(list){
int temp = list.get(1)+1;
list.set(1,temp);
}
}
}
package com.juhani.prototype.sync;
public class WorkerSyncObj extends Thread {
ArrayListWrapper listWrapper = null;
TestClass tc = null;
int number;
public WorkerSyncObj(int aNumber){
number = aNumber;
}
public void setListWrapper(ArrayListWrapper aListWrapper){
listWrapper = aListWrapper;
}
public void setTestClass(TestClass aTc){
tc = aTc;
}
public void run(){
int i = 1000;
for(int j=0;j<i;j++){
tc.testBlock(listWrapper);
System.out.println("Thread "+number+" is runing at loop "+j+" . index 1 value is:"+listWrapper.aList.get(1));
}
}
}
package com.juhani.prototype.sync.main;
import com.juhani.prototype.sync.ArrayListWrapper;
import com.juhani.prototype.sync.TestClass;
import com.juhani.prototype.sync.WorkerSyncObj;
public class TestMain {
public static void main(String[] args){
ArrayListWrapper list = new ArrayListWrapper();
TestClass tc = new TestClass();
WorkerSyncObj work1 = new WorkerSyncObj(1);
work1.setListWrapper(list);
work1.setTestClass(tc);
WorkerSyncObj work2 = new WorkerSyncObj(2);
work2.setListWrapper(list);
work2.setTestClass(tc);
WorkerSyncObj work3 = new WorkerSyncObj(3);
work3.setListWrapper(list);
work3.setTestClass(tc);
work1.start();
work2.start();
work3.start();
}
}
In the first case you lock on the this object while in the second on the list object. This might be a problem if you call the method from different objects but the list is the same. This is can be the reason of the exception in the first case.
Alternatively you could try some built-in concurrent types like Collections.synchronizedList or CopyOnWriteArrayList.
In java, every object instance has an intrinsic lock (as well as corresponding class itself). Synchronzied keywork is actually use the intrinsic lock for exclusive access, i.e.
syncrhonized method(...) {...}
is equal to
method(...) {
this.intrinsicLock.lock();
...;
this.intrinsicLock.unlock() }
And
synchronized( obj_ref ) { ... }
is equal to
obj_ref.intrinsicLock.lock();
{...}
obj_ref.instrinsicLock.unlock();
So, syncrhonized the method is not right for the protection of list (the parameter). There are two problems if you use the synchronized( list):
1. The granularity of exclusive access seems a little gross
2. Every list access wherever in the whole program need to use "synchronized( list )" too. This is a protocol (for the exclusive acess).
That's the reason why Java library provide quite some concurrent data structures.