I have the following Java code:
But the synchronized not work well, Help!
java.util.ConcurrentModificationException
java.util.ConcurrentModificationException at
java.util.HashMap$HashIterator.nextNode(HashMap.java:1442) at
java.util.HashMap$KeyIterator.next(HashMap.java:1466) at
java.util.AbstractCollection.toArray(AbstractCollection.java:196) at
Main.m(Main.java:68) at Main.lambda$main$0(Main.java:25) at
java.lang.Thread.run(Thread.java:748)
public class Main {
public static Set<Object> objectSet = new HashSet<>();
public static void main(String[] args) throws Exception {
new Thread(()->{m();}).start();
new Thread(()->{add();}).start();
}
public static void add() {
while (true){
objectSet.add(new Object());
}
}
public static void m(){
while(true){
try {
synchronized (objectSet) {
List a = Arrays.asList(objectSet.toArray(new Object[0]));
System.out.println(a.size());
}
}catch (Exception e){
e.printStackTrace();
}
try {
Thread.sleep(1000);
}catch (Exception e){
}
}
}
}
Can't synchronize (java.util.ConcurrentModificationException)
The writers should also synchronize on the same object
Change the add method as
public static void add() {
while (true) {
synchronized (objectSet) {
objectSet.add(new Object());
}
}
}
Related
I have a scenario in which I thread should monitor Clickhouse and the other one should sqlite. In order to load driver classes, I am using Class.forName("..."). Since the threads are starting at a time. I think it is going under deadlock situation..
Here is the piece of code that describes the issue.
public class ch {
public static void main(String[] args) throws Exception {
new OTTLCleaner().start(); // loading CH Driver
new CHThr().start(); // loading CH Driver
Spark.getInstance(); // loading Sqlite Driver
}
}
class OTTLCleaner extends Thread {
#Override
public void run() {
try {
System.out.println("Inside OTTL");
DBHelper.deleteTables();
...
} catch (Exception e) {
System.out.println(e);
}
}
}
class CHThr extends Thread {
#Override
public void run() {
try {
System.out.println("Inside CHThr");
DBHelper.CHConn();
...
} catch (Exception e) {
System.out.println(e);
}
}
}
class Spark implements Runnable {
private static class SingletonHelper {
private static final Spark INSTANCE = new Spark();
}
public static Spark getInstance() {
return SingletonHelper.INSTANCE;
}
private Spark() {
try {
System.out.println("Inside Spark");
DBHelper.SqliteConn();
...
} catch (Exception e) {
System.out.println(e);
}
}
#Override
public void run() {
...
}
}
class DBHelper {
public static void CHConn() throws ClassNotFoundException, SQLException {
Class.forName("ru.yandex.clickhouse.ClickHouseDriver");
System.out.println("CH");
...
}
static synchronized void SqliteConn() throws Exception {
Class.forName("org.sqlite.JDBC");
System.out.println("spark");
...
}
public static void deleteTables() throws Exception {
Class.forName("ru.yandex.clickhouse.ClickHouseDriver");
System.out.println("OTTl");
...
}
}
I added Thread.sleep in between the threads, it works. It is a bad approach in real world. I may get one more thread which may needs to load diff driver in future. What is the good approach to implement this without fail?
I'm trying to stop a java thread from a different class, but unable to figure out. I have looked into the below links, googled a lot from past 2 days but unable to nail down. May be a simple thing which i need to change but i'm out of options and hence posting it here.
Referred Links
java external threads (outside the class file it's used)
http://tutorials.jenkov.com/java-concurrency/creating-and-starting-threads.html
http://www.java2novice.com/java_thread_examples/
While typing the question, I referred the below links as well..
Stop a thread from outside
Below is my code sample. I'm able to start the WorkerThread from the MainThread and get into the loop. But unable to stop the thread started using the StopThread class.
I've also used the volatile option suggested in the below link.
http://tutorials.jenkov.com/java-concurrency/volatile.html
I feel I'm making a simple mistake, but not able to identify it.
//class WorkerThread
package main;
public class WorkerThread implements Runnable
{
public WorkerThread() {
isRunning = true;
}
public WorkerThread(boolean False) {
isRunning = False;
}
private volatile boolean isRunning;
public synchronized void stopThread() {
isRunning = false;
}
public synchronized boolean IsThreadRunning() {
return isRunning;
}
#Override
public void run()
{
int i = 1;
while(isRunning)
{
System.out.println("Loop " + i);
i++;
try { Thread.sleep(2000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
//class MainThread
package main;
public class MainThread
{
public static Thread t;
public static void main(String[] args)
{
t = new Thread(new WorkerThread());
t.start();
}
}
//class StopThread
package main;
public class StopThread
{
public static void main(String[] args)
{
//What should i write here to stop the thread started by MainThread
MainThread.t.interrupt();
}
}
public class MainThread
{
public static Thread t;
public static void main(String[] args)
{
t = new Thread(new WorkerThread());
t.start();
}
}
public class StopThread
{
public static void main(String[] args)
{
MainThread.t.interrupt();
}
}
It is not safe to call Thread.stop() it is listed as deprecated in JavaDocs
Also this may be just for the sake of this question, but why does your program have two main methods?
You have an opportunity to make use of what you defined volatile variable and gracefully come out of thread like below:
public class MainThread
{
public static WorkerThread workerThread;
public static void main(String[] args)
{
workerThread = new WorkerThread();
Thread t = new Thread(workerThread);
t.start();
}
}
public class StopThread
{
public static void main(String[] args)
{
Main.workerThread.stopThread();
}
}
Note: This solution works but not a perfect solution.
You can write and read value of isRunning variable from a properties file. This way you can have interaction between two different java processes. ThreadWorker just creates file upon initiation & and just makes attempt to read the file after that. StopThread modifies the properties file when triggered which should be picked up by ThreadWorker.
Check below example:
public class ThreadWorker implements Runnable
{
public volatile static boolean isRunning = false;
public ThreadWorker() {
Properties p = new Properties();
p.setProperty("isRunning", "1");
FileOutputStream out;
try {
//Writes all properties in appProperties file
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run()
{
int i = 1;
String status = "1";
while("1".equals(status))
{
status = getStatus();
System.out.println("Loop " + i);
i++;
try { Thread.sleep(2000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
public String getStatus() {
FileInputStream in;
Properties p = new Properties();
try {
in = new FileInputStream("appProperties");
p.load(in);
return p.getProperty("isRunning");
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//class StopThread
public class StopThread
{
public static void main(String[] args)
{
Properties p = new Properties();
p.setProperty("isRunning", "0");
FileOutputStream out;
try {
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//class StopThread
public class StopThread
{
public static void main(String[] args)
{
Properties p = new Properties();
p.setProperty("isRunning", "0");
FileOutputStream out;
try {
out = new FileOutputStream("appProperties");
p.store(out, "---Thread Status----");
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Make thread t a public member of class MainThread, and then just call MainThread.t.interrupt() from StopThread
i have an error in this code that's the thread set 2 value instead of one when the program start , the program mustn't set the next value before get the current
this is the main class
class DATA
{
private int value=0;
Lock lock;
Condition co;
Boolean IstReady=false;
public DATA()
{
IstReady=false;
lock = new ReentrantLock();
co=lock.newCondition();
}
public void set(int x) throws InterruptedException
{
lock.lock();// try
while(IstReady==true)
co.await();
value=x;
IstReady=true;
co.signal();
lock.unlock();
}
public int get()
{
int ret=0;
try{
lock.lock();
while(IstReady==false)
co.await();
ret=value;
co.signal();
//lock.unlock();
}
catch(Exception e)
{
System.out.println(e);
}
finally{
lock.unlock();
IstReady=false;
}
return ret;
}
}
}
}
and this the set() and get() class
class setter extends Thread
{
DATA D;
public setter(DATA X)
{
D=X;
}
#Override
public void run()
{
Random T=new Random();
while(true)
{
try {
int M=T.nextInt(1000);
System.out.println("setter set"+M);
D.set(M);
} catch (InterruptedException ex) {
Logger.getLogger(setter.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public class Newtest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
DATA x=new DATA();
setter s=new setter(x);
getter g=new getter(x);
s.start();
g.start();
}
}
i think the error is in the set() and get() method in DATA class
Is it true that notify works only after thread is finished? In code below I can't get notification until I comment while (true). How to tell main thread that part of thread job is done?
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
You should try to avoid using wait and notify with the newer versions of Java, as they're difficult to get right. Try using something like a BlockingQueue instead
public class ThreadMain {
public final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
System.out.println("notifying");
queue.offer(Boolean.TRUE);
System.out.println("notifying done");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
try {
d.queue.take(); // block until something is put in the queue
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
If you want to be notified when the Thread t completes, call t.join() in the calling Thread. This will block until t has finished its Runnable.
As user oddparity noted in the comments, you are calling wait() and notify() on different objects. A possible fix for this would be to make your SerialReader extend Thread rather than implement Runnable and then assigning reader to be a new instance of the SerialReader directly. :
public class ThreadMain {
public Thread reader;
private class SerialReader extends Thread {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new SerialReader();
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
If you want to use Runnable with wait()/notify() you can do it this way :
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
Thread thisThread = Thread.currentThread();
while (true) {
try {
Thread.sleep(3000);
synchronized (thisThread) {
System.out.println("notifying");
thisThread.notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String[] args) {
ThreadMain d = new ThreadMain();
d.reader.start();
synchronized (d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
public class Test {
public static void main(String[] args) {
try {
doSomething(new TestCallback() {
#Override
public void doCallback() {
throw new NullPointerException();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public static void doSomething(TestCallback callback){
callback.doCallback();
}
interface TestCallback {
public void doCallback();
}
}
RESULT:
java.lang.NullPointerException
at managers.concurrency.Test$1.doCallback(Test.java:11)
at managers.concurrency.Test.doSomething(Test.java:20)
at managers.concurrency.Test.main(Test.java:8)
In the above code we will get NullPointerException because the callback code is executed in the different part of stack. Is there a way to catch the such exceptions locally?
You are already catching the exception. Try something as follows -
try {
doSomething(new TestCallback() {
#Override
public void doCallback() {
throw new NullPointerException();
}
});
} catch (Exception e) {
System.out.println("Exception caught !!!");
}
Output:
Exception caught !!!