I have a multi threaded java application that retrieves usernames from a Postgresql database for processing.
I only want one account to be processed at a time by each thread so I have a column in my table which has the time stamp of last accessed and only accounts which have been accessed more than 30 seconds will be fetched. The SQL Query works below, I'm only posting it to be clear.
select * from account where (EXTRACT(EPOCH FROM (now() - last_accessed)) > 30 OR last_accessed is null) AND enabled = true order by random() limit 1
I have a synchronized block so only one thread can access the account retrieval process as the updating the time stamp takes a bid of time on the database.
public class TC extends Common implements Runnable
{
RegularExpr reg = new RegularExpr();
Database db = new Database();
public void run()
{
while (true)
{
try
{
ArrayList<Object> accountInfo = null;
synchronized (this)
{
accountInfo = db.getAccount();
db.updateAccountAccessTime((String) accountInfo.get(0));
Thread.sleep(3000);
}
System.out.println((String) accountInfo.get(0));
Thread.sleep(9999999);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
My main class
public class Main
{
public static void main(String[] args)
{
for (int i = 0; i < 3; i++)
{
System.out.println("Inside loop to create threads!");
Thread newThread = new Thread(new TC());
newThread.start();
}
}
}
But I still receive the same account when I run the program. What I am doing incorrectly?
Each thread is executing with a different instance of TC.
new Thread(new TC())
So when you do:
synchronized (this)
Each thread is synchronizing on a different object (different TC), so they are not competing with each other at all. Essentially, the synchronized block becomes pointless.
I'm not sure how good of an idea this is, but what you are trying to do would be accomplished like this:
synchronized (TC.class)
or, perhaps a bit cleaner, by declaring a static member in the class and synchronizing on that:
private static final Object _lock = new Object();
....
synchronized(_lock)
The whole point of synchronization is, when there is a shared resource and multiple threads accessing it.
In your case,same TC instance can be passed into new Thread.then 3 threads start working on it.
Now the db operation needs to be protected, since you need to get account info and also update timestamp.so synchronize on a lock object specifically or this.
private Object lock = new Object();
Related
I'm new to multithreading and don't even understand what to do with a thread in my application. The application is a console game. The player chooses a hero, clan and actions. Gold is credited to the treasury for various actions. You can add from your pocket, complete a task or win a battle. Each action is a separate class. All operations are saved to the database. Here is the code that creates the operation object, it also saves changes to the clan treasury
public class OperationService {
OperationDAO operationDAO = new OperationDAO();
private static ClanService clanService = new ClanService();
public void createOperation(String reason, int sum) {
Hero currentHero = CurrentHero.getCurrentHero();
Clan currentClan = CurrentHero.getClan();
LocalDateTime currentDateTime = LocalDateTime.now();
Operation operation = new Operation();
operation.setClan(currentClan);
operation.setHero(currentHero);
operation.setReason(reason);
operation.setSum(sum);
operation.setAmountBefore(currentClan.getGold());
operation.setAmountAfter(currentClan.getGold() + sum);
operation.setDateTime(currentDateTime);
operationDAO.save(operation);
clanService.changeAmount(sum);
}
The problem is that it is implied that many players will simultaneously perform different actions and change the treasury of their clan. According to the task, it is necessary to enter multithreading, but the amount of the clan treasury before and after should be displayed correctly.
I also created a thread with the launch of the game, which pulls a large chain of method calls from different classes.
public class ThreadGame extends Thread {
HeroService heroService = new HeroService();
public ThreadGame() {
this.start();
}
#Override
public void run() {
heroService.startGame();
}
}
Question 1. Can methods from the chain also be considered threads? Or are they no longer part of it?
I also tried to create tests for my application, but some operations are not saved in the database and synchronized does not help.
public class Test extends Thread {
HeroDAO heroDAO = new HeroDAO();
OperationService operationService = new OperationService();
#Override
public void run() {
Hero hero1 = heroDAO.findById(4L);
operationService.createOperationForTest(hero1, "Победа в бою", 20);
operationService.createOperationForTest(hero1, "Победа в бою", 20);
}
}
public class App {
public static void main(String[] args) {
Test test = new Test();
Test test1 = new Test();
test.start();
test1.start();
}
}
I synchronized the createOperationForTest method, but the data is still stored incorrectly.
Question 2. Where to specify synchronized?
All the code you write in the run() function, will run in the thread that will be created when you execute thread.start();
For example:
In your class ThreadGame you have this function:
#Override
public void run() {
System.out.println("Hello, I'm a thread");
heroService.startGame();
}
When you execute the .start() function, a thread will be created and this thread will then execute the code in the run() function.
So in this case it will output "Hello, I'm a thread" and then execute your heroService.startGame() function.
All the code that you wrote in startGame() will be executed on this thread.
Note that you can create another thread, inside a thread.
Threads exist to provide asynchronous execution.
If you need to let a thread wait until another thread has completed something, you can use Semaphores! Here's a link to learn more about semaphores.
Elisaveta.
To learn about multi-threading I would recommend:
official Java tutorial on concurrency
Java Concurrency in Practice
But in short a thread lets us run something in parallel and use multiple cores of our CPU.
A good example of thread usage is a web-server.
The web-server receives HTTP-requests and for each requests it replies back with an HTTP-response.
In order to use all available CPU cores the web-server uses several threads (it's usually called "thread pool").
When a new HTTP-request arrives to the web-server the main thread delegate the task of the request processing to one of the vacant threads in the thread pool.
The thread is busy until it finishes the request processing and sends the HTTP-response, but after that it again becomes vacant and can be used to process new requests.
It's a frequent pattern in Java to have a thread pool to perform tasks in parallel.
In your case you can use threads to save new operations in parallel.
Something like this:
public class App {
final HeroDAO heroDAO = new HeroDAO();
final OperationService operationService = new OperationService();
final ExecutorService threadPool;
App() {
var numCores = Runtime.getRuntime().availableProcessors();
threadPool = Executors.newFixedThreadPool(numCores);
}
void saveNewOperation(long heroId, String reason, int sum) {
threadPool.submit(() -> {
var hero = heroDAO.findById(heroId);
operationService.createOperationForTest(hero, reason, sum);
});
}
void stop() throws InterruptedException {
threadPool.shutdown();
threadPool.awaitTermination(10, TimeUnit.SECONDS);
threadPool.shutdownNow();
}
public static void main(String[] args) throws InterruptedException {
var app = new App();
try {
app.saveNewOperation(4L, "Победа в бою", 20);
app.saveNewOperation(5L, "Победа в бою", 30);
app.saveNewOperation(6L, "Победа в бою", 40);
app.saveNewOperation(7L, "Победа в бою", 50);
} finally {
app.stop();
}
}
}
With multiple threads you should be careful with static variables (it seems like CurrentHero in your code is a static variable that stores current hero).
When you process two operations in parallel there could be two current heroes.
In multi-threaded applications such information is usually passed explicitly to methods (sometimes multiple properties are grouped in a single context object which is usually a Map<String,Object> that stores an object-value for every property name).
synchronized is used when we want to guarantee that some block of code can only be executed by one thread at a same time.
Often we guard with synchronized a code that works with some shared resource (for example an established connection to the database might only be used by one thread at the same time).
Also synchronized allows us to guarantee that some group of actions happens atomically (i.e. the actions aren't interleaved with actions in parallel threads).
For your example synchronized might be required:
around clanService.changeAmount(sum): here we have a shared resource "treasury".
If the operation changeAmount consists internally of several actions, then you might want to execute them atomically.
around operationDAO.save(operation): here we have a shared resource "operation storage".
Again if save consists internally of multiple actions, then you might want to execute them atomically.
Additionally if operationDAO use internally connection to a database, then this connection might require to be used by one thread at a time
around
operationDAO.save(operation);
clanService.changeAmount(sum);
If you want these two operations to execute as a single atomic block.
I am using the spring framework under tomcat to write service that can handle multiple concurrent requests. There is a static variable declared in my service class to be shared across all the threads and protected by a read-write lock. This static collection is read and written to periodically. Each time I update I acquire the write lock and when I read it I acquire the read lock.
The data stored in the collection is entries from a database table. So it is a collection of type List. Basically I have a table that gets updated rarely and so I am caching it in the process memory.
Now there are times when I need to log this data so can I log the return object without acquiring the lock in the method. Or will that cause a race condition? The logging is for the purpose of debugging.
Also, the returned value of the collection is only read only and is not modified by any method. No one outside of the service object uses this Collection.
I feel this should work because when a new collection is allocated the old collection will only go away if all references to it have gone away. And while updating no new references to old or new object are allowed till the write lock is unlocked.
The code looks as follows:
class ObjService {
private static Collection<OtherObj> _staticCollection;
private static ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock(true);
private Collection<OtherObj> getCollection () {
Collection<OtherObj> retVal = null;
rwlock.readLock().lock();
if (_staticCollection != null) {
retVal = _staticCollection;
rwlock.readLock().unlock();
log (retVal);
}
else {
rwlock.readLock().unlock();
ReloadCollectionFromDB ();
rwlock.readLock().lock();
retVal = _staticCollection;
rwlock.readLock().unlock();
}
}
private ReloadCollectionFromDB () {
Collection<OtherObj> otherObjCol = null;
try {
otherObjCol = objRepo.findAll ();
}
catch (Exception ex) {
// log exception
return;
}
rwlock.writeLock().lock();
_staticCollection = otherObjCol;
rwlock.writeLock().unlock();
}
// periodically get data from DB
#Scheduled(initialDelayString = "120000", fixedDelayString = "540000")
void readLoadCache () {
ReloadCollectionFromDB ();
}
}
If there are better ways of doing this, I would appreciate some guidance.
Many thanks,
~Ash
I have a database which contains e-mails to be sent. I'm using multiple threads to send out these e-mails. The approach I'm using is that each thread will query the database, get N e-mails in memory and mark those as being sent. Another thread will see those N e-mails as marked and move on and fetch the next N entries.
Now this isn't working as before thread1 can update the entries as being sent, thread2 queries for the e-mails and thus both threads end up getting the same set of e-mails.
Each thread has its own connection to the database. Is that the root cause of this behaviour? Should I be just sharing one connection object across all the threads?
Or is there any better approach that I could use?
My recommendation is to have a single thread take care of querying the database, placing the retrieved emails in a thread-safe queue (e.g. an ArrayBlockingQueue, which has the advantage of being bounded); you can then have any number of threads removing and processing emails from this queue. The synchronization overhead on the ArrayBlockingQueue is fairly lightweight, and this way you don't need to use database transactions or anything like that.
class EmailChunk {
Email[] emails;
}
// only instantiate one of these
class DatabaseThread implements Runnable {
final BlockingQueue<EmailChunk> emailQueue;
public DatabaseThread(BlockingQueue<EmailChunk> emailQueue) {
this.emailQueue = emailQueue;
}
public void run() {
EmailChunk newChunk = // query database, create email chunk
// add newChunk to queue, wait 30 seconds if it's full
emailQueue.offer(newChunk, 30, TimeUnit.SECONDS);
}
}
// instantiate as many of these as makes sense
class EmailThread implements Runnable {
final BlockingQueue<EmailChunk> emailQueue;
public EmailThread(BlockingQueue<EmailChunk> emailQueue) {
this.emailQueue = emailQueue;
}
public void run() {
// take next chunk from queue, wait 30 seconds if queue is empty
emailChunk nextChunk = emailQueue.poll(30, TimeUnit.SECONDS);
}
}
class Main {
final int queueSize = 5;
public static void main(String[] args) {
BlockingQueue<EmailChunk> emailQueue = new ArrayBlockingQueue<>(queueSize);
// instantiate DatabaseThread and EmailThread objects with this queue
}
}
You need to have a way to share one method // code to control the concurrence. Sincronize the statements to get the emails and mark them. Then sent the e-mails. Something like this:
public void processMails(){
List<String> mails;
synchronized(this){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
This method could be in your DAO Facade where all threads can access.
EDIT:
if you have multiples instances of DAO class:
public void processMails(){
List<String> mails;
synchronize(DAO.class){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
Other alternative
private static final Object LOCK = new Object();
public void processMails(){
List<String> mails;
synchronize(LOCK){
mails = getMails();
markMails(mails);
}
sendMails(mails);
}
Is it bad programming to initialize two threads with the same instance of a runnable? What difference would it make to initialize with separate instances of a runnable, and does sharing memory locations at all for the same instance of a runnable have anything to do with performance?
public static void main(String[] args)throws Exception {
H h = new H();
H h2 = new H();
Thread j = new Thread(h);
j.setName("11");
Thread jj = new Thread(h);//instead of new H()
jj.setName("22");
j.start();
jj.start();
}
class H implements Runnable {
public void run() {
while(true) {
System.out.println(Thread.currentThread().getName());
}
}
}
It's absolutely fine to do it so long as the code you're running is designed to support that. Not only will it save some memory by having a single instance instead of multiple instances, but if those threads are trying to communicate via shared data, then it may be absolutely required!
Admittedly communicating via shared state is where threading often gets tricky, so this needs to be done carefully, but from the point of view of the threading system itself, there's absolutely no problem in having two threads call the run method of a single Runnable instance.
Since H doesn't have any instance state, using multiple instances won't matter. You need to take care when the Runnable instances start storing state.
public class Main implements Runnable {
volatile int i;
public void run() {
for (i = 0; i < 100; i++) {
System.out.println(i);
}
}
public static void main(String[] args) {
Main a = new Main();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.start();
t2.start();
}
}
What gets printed? When you do need to share state between threads, it's a good idea to use the classes in java.util.concurrent. They were written primarily by an expert in multithreading (Doug Lea, author of Concurrent Programming in Java) and tested by many people. Save yourself some heartache. :)
Is it bad programming to initialize two threads with the same instance of a runnable?
Not specifically. However, if the Runnable instance has instance fields, then you'll need to make sure that all access to the fields by the thread is properly synchronized, and this will make the code more complicated.
What difference would it make to initialize with separate instances of a runnable, and does sharing memory locations at all for the same instance of a runnable have anything to do with performance?
The memory saved by sharing a Runnable instance between multiple threads is insignificant ... unless the Runnable holds a significant amount of instance data. (And if it does, the chances are that this will make the instance non-shareable.)
Your H class is an example where sharing instances is safe, but pointless since the memory saving is insignificant. (A Runnable object with no instance fields occupies roughly 8 to 16 bytes, depending on the platform.)
To make understand easily(based on the comment of Stephen), added the below program block about the impact of accessing the instance variable from a non-synchronized block with the same instance of Runnable displays the unexpected results.
public class SynchronizedInstanceMethod implements Runnable{
private int counter;
public SynchronizedInstanceMethod(int counterValue){
this.counter = counterValue;
}
private synchronized void displayMessage(){
System.out.println(" Display Message ");
}
private void modifyCounter(){
this.counter++;
System.out.println("Value -- "+ this.counter);
}
#Override
public void run() {
this.displayMessage();
this.modifyCounter();
}
public static void main(String[] args) {
SynchronizedInstanceMethod instance = new SynchronizedInstanceMethod(5);
new Thread(instance).start();
new Thread(instance).start();
}
}
I have the following codes. I expected one thread to execute its synchronized method completely and then allow another one to access the same method. However, this is not the case.
public class Threads {
/**
* #param args
*/
public static void main(String[] args) {
//Thread Th = new Threads();
Thread th = new Thread (new thread1 ());
th.start();
Thread th1 = new Thread (new thread1 ());
th1.start();
}
}
class thread1 implements Runnable{
String name = "vimal";
public void run() {
System.out.println("Runnable "+this.name);
setNAme("Manish");
}
public synchronized void setNAme(String name){
try {
System.out.println("Thread "+Thread.currentThread().getName());
wait(1000);
this.name = name;
System.out.println("Name "+this.name);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I have one output as
Runnable vimal
Thread Thread-0
Runnable vimal
Thread Thread-1
Name Manish
Name Manish
What is the use of synchronized here and how do I make my method to run completely before another accesses it?
synchronized has no effect here because you are not synchronizing on the same object in both cases. When applied to an instance method, the synchronized keyword causes the method to be synchronized on this. So in each case you are synchronizing on the instance of thread1, and there are two of those.
The more interesting test would be when you run the same instance of thread1 in two threads simultaneously. In that case, calling wait(1000) is a very bad thing to do because (as documented) it releases the lock on this. You want to use Thread.sleep(1000) instead in your code.
If you need to have two instances of thread1, you need to synchronize on some shared object, possibly like this:
private static final Object lockObject = new Object();
public void setName(String newName) {
synchronized(lockObject) {
doSetName(newName);
}
}
You will have to remove the call to wait(1000). It looks like what you actually want is a call to Thread.sleep(1000), if you simply want to pause the current thread, this does not release ownership of any monitors.
From the javadoc for Object.wait().
This method causes the current thread (call it T) to place itself in
the wait set for this object and then to relinquish any and all
synchronization claims on this object. Thread T becomes disabled for
thread scheduling purposes and lies dormant until one of four things
happens:
Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be
awakened.
Some other thread invokes the notifyAll method for this object.
Some other thread interrupts thread T.
The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into
consideration and the thread simply waits until notified.
The thread T is then removed from the wait set for this object and
re-enabled for thread scheduling. It then competes in the usual manner
with other threads for the right to synchronize on the object; once it
has gained control of the object, all its synchronization claims on
the object are restored to the status quo ante - that is, to the
situation as of the time that the wait method was invoked. Thread T
then returns from the invocation of the wait method. Thus, on return
from the wait method, the synchronization state of the object and of
thread T is exactly as it was when the wait method was invoked.
UPDATE: As has been mentioned in other answers, you are not synchronizing on the same object. Once you do, you will still suffer the same output, due to the issue I have mentioned. You will need to fix both for your desired results.
The output is correct, you are creating to independent threads that do not share any data. Thus both threads start with first string, and after some time, the string is changed and printed.
You're creating 2 thread1 objects. They each have their own setNAme method. Synchronized methods only synchronize on the object, not the class. Unless the method is static.
You have two Threads here with independent name variables and independent monitors, so each Thread is only accessing its own members. If you want to have the threads interact with each other you'll have to implement such an interaction.
you are creating two separate thread1 objects and running them. Each thread has it's own copy of the name variable as well as the setName function. Make them both static and you will see the effects of synchronization.
You are locking on two different instance of the objects where you dont need any synchronization at all. You need to synchronize only if you are working on a shared data. I think you meant to write a test like the below.
If you test this, you will realize that the second thread will wait until the first thread is completed with the synchronized method. Then take out the synchronized word and you will see both threads are executing at the same time.
public class SynchronizeTest {
public static void main(String[] args) {
Data data = new Data();
Thread task1 = new Thread(new UpdateTask(data));
task1.start();
Thread task2 = new Thread(new UpdateTask(data));
task2.start();
}
}
class UpdateTask implements Runnable {
private Data data;
public UpdateTask(Data data) {
this.data = data;
}
public void run() {
try {
data.updateData();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Data {
public synchronized void updateData() throws InterruptedException {
for (int i = 0; i < 5; i++) {
Thread.sleep(5000);
System.out.println(i);
}
}
}