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?
2
Answers
run()
function, will run in the thread that will be created when you executethread.start();
For example:
In your class
ThreadGame
you have this function:When you execute the
.start()
function, a thread will be created and this thread will then execute the code in therun()
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.
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:
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:
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 aMap<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: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.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 timeIf you want these two operations to execute as a single atomic block.