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;
}
Related
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 a very simple class:
public class IdProvider {
private Map<String,AtomicLong> idMap;
public IdProvider(){
idMap = new HashMap<>();
}
public long getAvailableId(String conversation){
AtomicLong id = idMap.get(conversation);
if(id == null){
id = new AtomicLong(0);
idMap.put(conversation,id);
}
return id.getAndIncrement();
}
}
Different methods asynchronously may pass the same conversation identifier and call getAvailableId() where they will be returned a unique id.
Is this thread safe? I'm I guaranteed that the no two methods will receive the same id or do I need to opt for something else?
There's multiple ways to make this thread safe, but below is the simplest, I think. First, you need to safely publish the initial Map. Then you need to make each access of that map thread safe.
public class IdProvider {
private final Map<String,AtomicLong> idMap;
public IdProvider(){
idMap = new HashMap<>();
}
public synchronized long getAvailableId(String conversation){
AtomicLong id = idMap.get(conversation);
if(id == null){
id = new AtomicLong(0);
idMap.put(conversation,id);
}
return id.getAndIncrement();
}
}
The final keyword is one way to provide "safe publication". (That's an actual term in Java, look it up.)
And without being tricky, just synchronizing the whole method is the easiest way to provide both synchronization and atomicity. You shouldn't try to do more unless you can profile this code and determine that it is in fact a performance bottle-neck. Keep It Simple.
This isn't thread safe.
public long getAvailableId(String conversation){
AtomicLong id = idMap.get(conversation);
// Thread could be paused here, causing bad interleavings
// If now a similar call to "getAvailableId" is done you will have two times the same id
if(id == null){
id = new AtomicLong(0);
idMap.put(conversation,id);
}
return id.getAndIncrement();
}
Make the method synchronized to avoid possible bad interleavings and data races.
When you need to use multiple providers working on same set of ids at the same time,
public class IdProvider {
private static Map<String,Long> idMap;
static
{
idMap = new HashMap<>();
}
public Object lock=new Object();
public IdProvider(Object l){
lock=l;
}
public long getAvailableId(String conversation){
// do other work
synchronized(lock)
{
Long id = idMap.get(conversation);
if(id == null){
id = new Long(0);
idMap.put(conversation,id);
}
return idMap.put(conversation,id+1);
}
}
}
Object lock=new Object();
... in a thread:
IdProvider provider=new IdProvider(lock); // providing from a thread
... in another thread:
IdProvider provider2=new IdProvider(lock); // providing from another
I am making a particle emitter.
Every "Rendered" object is stored in a HashSet, and when there's lots of particles on the screen, the console spits out concurrent modification exceptions. I usually have a short lifetime on these particles so they get deleted after several seconds, but I am sure this could potentially be a problem in the future. How can I fix this?
EDIT: Code:
public class UpdatedManager {
private static Set<Updated> updates = new HashSet<>();
private UpdatedManager() {}
public static Set<Updated> getUpdates() {
return new HashSet<Updated>(updates);
}
public static boolean registerUpdated(Updated u) {
return updates.add(u);
}
public static boolean unregisterUpdated(Updated u) {
return updates.remove(u);
}
public static void update() {
for (Updated up : new HashSet<Updated>(updates))
up.update();
}
public static Set<GameObject> getGameObjects() {
Set<GameObject> objs = new HashSet<>();
for (Updated up : new HashSet<Updated>(updates)) {
if (up instanceof GameObject)
objs.add((GameObject) up);
}
return objs;
}
public static Set<GameObject> getGameObjectsByName(String name) {
Set<GameObject> objs = new HashSet<>();
for (GameObject go : new HashSet<GameObject>(getGameObjects())) {
if (go.getName() != null && go.getName().equals(name))
objs.add(go);
}
return objs;
}
public static Set<Particle> getParticles() {
Set<Particle> parts = new HashSet<>();
for (Updated up : new HashSet<Updated>(updates)) {
if (up instanceof Particle)
parts.add((Particle) up);
}
return parts;
}
}
A ConcurrentModificationException means you modified the set while iterating over it. It does not mean the set is full.
For example, the following code will throw a ConcurrentModificationException:
Set<String> set = new HashSet<>();
set.add("Hello");
for(String s : set)
set.add(s+" world");
Note that you are not guaranteed to get a ConcurrentModificationException, so you should avoid catching it. You should instead fix your code so that it doesn't cause the problem.
What makes you think that the set is full?
Concurrent modification exceptions mean that the set is being accessed by different threads in an unsafe manner.
Try a synchronised set using the Collections utilities
HashSet hashSet = new HashSet();
Set set = Collections.synchronizedSet(hashSet);
or use the synchronized keyword for the method accessing the set.
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 :=) )
I had posted somewhat similar question before also. I got clarification for my doubts as well. But still I need something more. The Hashmap will be initialized with the enum object as the key and a threadpool instance as the value. I am confused as of how to initialize the HashMap for every object been called by some other process ..To make clear :
My program, MyThreadpoolExcecutorPgm.java initializes a HashMap
My Progran AdditionHandler.java requests a thread from the HashMap by passing ThreadpoolName (enum). I am getting "No thread available from HashMap" message. Please do help me.
Below given is my code:
public class MyThreadpoolExcecutorPgm {
enum ThreadpoolName {
DR, BR, SV, MISCELLENEOUS;
}
private static String threadName;
private static HashMap<ThreadpoolName, ThreadPoolExecutor>
threadpoolExecutorHash;
public MyThreadpoolExcecutorPgm(String p_threadName) {
threadName = p_threadName;
}
public static void fillthreadpoolExecutorHash() {
int poolsize = 3;
int maxpoolsize = 3;
long keepAliveTime = 10;
ThreadPoolExecutor tp = null;
threadpoolExecutorHash = new HashMap<ThreadpoolName, ThreadPoolExecutor>();
for (ThreadpoolName poolName : ThreadpoolName.) // failing to implement
{
tp = new ThreadPoolExecutor(poolsize, maxpoolsize, keepAliveTime,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
threadpoolExecutorHash.put(poolName, tp);
}
}
public static ThreadPoolExecutor getThreadpoolExcecutor(
ThreadpoolName poolName) {
ThreadPoolExecutor thread = null;
if (threadpoolExecutorHash != null && poolName != null) {
thread = threadpoolExecutorHash.get(poolName);
} else {
System.out.println("No thread available from HashMap");
}
return thread;
}
}
AdditionHandler.java
public class AdditionHandler{
public void handle() {
AddProcess setObj = new AddProcess(5, 20);
ThreadPoolExecutor tpe = null;
ThreadpoolName poolName =ThreadpoolName.DR; //i am using my enum
tpe = MyThreadpoolExcecutorPgm.getThreadpoolExcecutor(poolName);
tpe.execute(setObj);
}
public static void main(String[] args) {
AdditionHandler obj = new AdditionHandler();
obj.handle();
}
}
I suspect you're just looking for the static values() method which is added to every enum:
for (ThreadpoolName poolName : ThreadpoolName.getValues())
Alternatively, you can use EnumSet.allOf():
for (ThreadpoolName poolName : EnumSet.allOf(ThreadpoolName.class))
(As Bozho says, EnumMap is a good alternative here. You still need to loop through the enum values.)
First, you'd better use EnumMap. Then make sure you have filled the map before you invoked the method.
You can iterate through enum values by one of (in descending order of preference)
for(Enum value : Enum.values())
for(Enum value : EnumSet.allOf(Enum.class))
for(Enum value : Enum.class.getEnumConstants())
But you should also be using an EnumMap.