Spring Boot shared thread - java

I am developing my Spring boot application wich
gets two requests: /start and /stop.
I need to create one shared thread for all clients requests.
When the first request "/start" will be received from client, app will create one thread shared by local variable T1.
When the second request "/stop" will be received, app will set boolean variable of thread "stopped" to stop it and the thread should stop.
Is next code provides safe for this shared thread?
Should i use the local variable for thread object or need to
do it by another way?
package com.direct.webflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#EnableAutoConfiguration
#Controller
public class WebApp {
ThreadDemo T1;
#RequestMapping("/start")
#ResponseBody
String start() {
synchronized(this){
if (T1 == null || T1.stopped) {
T1= new ThreadDemo( "Thread-1");
T1.start();
} else {
return "Already started!";
}
}
return "Thread started!";
}
#RequestMapping("/stop")
#ResponseBody
String end() {
if (T1 == null) {
System.out.println("Not started!");
return "Not started!";
} else if (!T1.stopped) {
T1.stopped=true;
System.out.println("Trying to stop!");
return "Stopped!";
} else {
return "Already stopped!";
}
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebApp.class, args);
}
}
package com.direct.webflow;
public class ThreadDemo extends Thread {
private Thread t;
private String threadName;
public volatile boolean stopped=false;
ThreadDemo(String name){
threadName = name;
System.out.println("Creating " + threadName );
}
public void run() {
int i=0;
System.out.println("Running " + threadName );
while (!stopped) {
System.out.println("Thread: " +this.isInterrupted()+ threadName + ", " + i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Thread: STOP!");
break;
}
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start ()
{
stopped=false;
System.out.println("Starting " + threadName );
if (t == null)
{
t = new Thread (this, threadName);
t.start ();
}
}
}

This is very close. You need to add the synchronized(this) block in your controller end() method. Otherwise you may have a race condition if /stop and /start are being called simultaneously.
Since Spring controllers are singletons you are OK to use a member variable like you have done here.

Related

volatile in spring controller not working

here is the code segment
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
class VolatileTest{
private static boolean stop = false;
public void go() throws Exception{
new Thread(()->{
System.out.println("thread started in " + Thread.currentThread().getName());
int counter = 0;
while (!stop){
counter++;
};
// #1
System.out.println("stopped at i=" + counter + " in " + Thread.currentThread().getName());
}).start();
Thread.sleep(1000);
stop = true;
}
}
#RestController
public class MyVolatileController {
#GetMapping("/volatile/test")
public String test(){
new Thread(()->{
try{
new VolatileTest().go();
}catch(Exception e){}
}).start();
return "volatile";
}
public static void main(String[] args) throws Exception{
new Thread(()->{
try{
new VolatileTest().go();
}catch(Exception e){}
}).start();
}
}
the expected behavior: when called, the program will never reach #1, since stop is not volatile, and the change made by other thread will not been seen immediately by the current thread.
Question: when it is started in public void static main of the class, it behaves as expected, however, when started inside a spring controller method, it does reach #1. why is that happening ?

why main thread is also call the thread pool's execute() method?

I am testing the ThreadPoolExecutor. I print out some debug info in the customized ThreadPoolExecutor's execute() method. The execute() method is called by an instance of the customized ThreadPoolExecutor. When I look at the print out, I found there are some duplicated print out which is from the main thread. I am wondering why the main thread calls the customized ThreadPoolExecutor's execute() method? The runnable code is attached here:
----------Thead: main/1
[PoolSize/CorePoolSize] [1/2]
----------Thead: pool-1-thread-1/11
[PoolSize/CorePoolSize] [1/2]
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class MyThreadPoolExecutorTest2
{
private List<MyRunnable> myRunnables = new ArrayList<>();
public static void main(String[] args)
{
new MyThreadPoolExecutorTest2().test();
}
public void test()
{
int poolSize = 2;
int maxPoolSize = 6;
int threadPoolKeepAliveTimeInSec = 30;
ExecutorService threadPoolExecutor =
new MySimpleThreadPoolExecutor2(poolSize, maxPoolSize, threadPoolKeepAliveTimeInSec);
int numOfThread = 5;
System.out.println("Start thread pool test with corePoolSize=" + poolSize + ", maxPoolSize=" + maxPoolSize
+ ", actualThreads=" + numOfThread);
for (int i = 0; i < numOfThread; i++)
{
MyRunnable tempRunnable = new MyRunnable(i + 1, "PoolTest" + (i + 1));
myRunnables.add(tempRunnable);
threadPoolExecutor.execute(tempRunnable);
}
System.out.println("********* wait for a while");
try
{
Thread.sleep(20000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("^^^^^^^^^^ shutdown them all");
for (MyRunnable runnable : myRunnables)
{
runnable.shutdown();
}
System.out.println("Ended thread pool test.");
System.exit(0);
}
public class MyRunnable implements Runnable
{
private int id = 0;
private String name = "";
private boolean shutdown = false;
public MyRunnable(int id, String name)
{
this.id = id;
this.name = name;
}
#Override
public void run()
{
System.out.println("++++ Starting Thread: " + id + ":" + name);
while (!shutdown)
{
try
{
Thread.sleep(200);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println("---- Ended Thread: " + id + ":" + name);
}
public void shutdown()
{
shutdown = true;
}
}
}
class MySimpleThreadPoolExecutor2 extends ThreadPoolExecutor
{
private static int peakActiveThreads = 0;
private String taskInfo = "";
public MySimpleThreadPoolExecutor2(int nThreads, int maxThreads, int threadPoolKeepAliveTimeInSec)
{
super(nThreads, maxThreads, threadPoolKeepAliveTimeInSec * 1000L, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
System.out.println("MySimpleThreadPoolExecutor::MySimpleThreadPoolExecutor(), threadPoolSize=" + nThreads
+ ", maxThreadCount=" + maxThreads + ", threadPoolKeepAliveTimeInSec=" + threadPoolKeepAliveTimeInSec);
}
#Override
public void beforeExecute(Thread t, Runnable r)
{
int activeCount = getActiveCount();
if (MySimpleThreadPoolExecutor2.peakActiveThreads < activeCount)
{
MySimpleThreadPoolExecutor2.peakActiveThreads = activeCount;
}
taskInfo = r.toString();
String msg =
"BeforeE thread(name:id)::" + t.getName() + ":" + t.getId() + ", task::" + r.toString() + "\n"
+ threadPoolInfoStr();
System.out.println("ThreadInfo before, MySimpleThreadPoolExecutor::beforeExecute(), " + msg);
super.beforeExecute(t, r);
}
#Override
public void execute(Runnable command)
{
beforeExecute(Thread.currentThread(), command);
super.execute(command);
}
public String threadPoolInfoStr()
{
return String
.format("----------Thead: %s/%d\n[PoolSize/CorePoolSize] [%d/%d]\nActive: %d\nCompleted: %d\nTask: %d"
+ "\nisShutdown: %s\nisTerminated: %s\npeakActiveThreads: %d\nTaskInfo: %s\nQueueSize: %d----------",
Thread.currentThread().getName(), Thread.currentThread().getId(), getPoolSize(),
getCorePoolSize(), getActiveCount(), getCompletedTaskCount(), getTaskCount(), isShutdown(),
isTerminated(), MySimpleThreadPoolExecutor2.peakActiveThreads, taskInfo, getQueue().size());
}
}
Well, you explicitly call beforeExecute from the overridden execute() method in your subclass :
#Override
public void execute(Runnable command)
{
beforeExecute(Thread.currentThread(), command);
super.execute(command);
}
As the execute method is called from the client thread (in your case the main thread) it prints out an entry for the calling thread too. The super class however calls the beforeExecute method from its worker thread, prior to executing a submitted task.
Note the javadoc for beforeExecute :
Method invoked prior to executing the given Runnable in the given thread. This method is invoked by thread t that will execute task r, and may be used to re-initialize ThreadLocals, or to perform logging.
Your explicit invocation from execute() is an extra invocation from the calling thread.
I am wondering why the main thread calls the customized ThreadPoolExecutor's execute() method?
because it is explicitely called in the code:
public static void main(String[] args) {
new MyThreadPoolExecutorTest2().test();
}
public void test() {
...
threadPoolExecutor = new MySimpleThreadPoolExecutor2();
...
threadPoolExecutor.execute(tempRunnable);
^^^^^^^
...
}

Ski lift with capacity equals N.

I am learning about multithreading. It's my first task. I wrote this code and i can't move on. Task:
Ski lift with capacity equal N.
Clients have a weight (random Ki value) and They are threads that execute in
loop:
downhill(sleep(big random value)
Try to get into the lift (if the total weight of customers is
Less than or equal to N).
If it failed - they are waiting (sleep(small random value)
and re-execute the previous point.
if it was successful - they go up.
public class Client extends Thread
{
private SkiLift lift;
private int weight;
public Client(SkiLift l, int w)
{
this.lift = l;
this.weight=w;
}
public int getWeight()
{
return weight;
}
public void run()
{
for (int i =0; i<10; i++)
{
lift.downhill(this);
lift.goIn(this);
this.setPriority(MAX_PRIORITY);
lift.drive(this);
lift.goOut(this);
this.setPriority(5);
}
}
}
public class SkiLift
{
private static int actualLoad=0;
private static final int CAPACITY=300;
synchronized public void goIn(Client client)
{
try
{
System.out.println("Client " + client.getId() + " try to get into the lift");
while (actualLoad>CAPACITY)
{
System.out.println("The Lift is full!");
client.sleep((long) (Math.random()*1000));
wait();
}
}
catch (InterruptedException e) {}
System.out.println("Client " + client.getId() + "get into the lift " );
actualLoad+=client.getWeight();
System.out.println("actual load = " + actualLoad);
}
synchronized public void goOut (Client client)
{
System.out.println("Client "+ client.getId() + " leave the lift ");
actualLoad-=client.getWeight();
System.out.println("Actual load = " + actualLoad);
notifyAll();
}
public void downhill(Client client)
{
System.out.println("Client nr: " + client.getId()+ " downhill ");
try
{
client.sleep((long) (Math.random()*10000));
}
catch (InterruptedException e){}
}
public void drive(Client client)
{
try
{
client.sleep(9000);
}
catch (InterruptedException e){e.printStackTrace();}
}
}
I have three problems and i can't solve them:
The first who will enter must to be the first who has attempted to enter. (Just like in a queue)
The client who first came on the lift must also be the first to go down.
What is the moniotor in my program?
Thanks in advance :)
I think this question belongs to Codereview
Your Client should have a state like "topOfTheMountainReached", "liftStationReached", "liftEntered", ...
Your Client then waits for this events to happen. That's also the answer to your question which element to monitor - the state, or the client itself.
For the queue you can use a ArrayListBlockingQueue.
Your SkiLift then has to wait for new Clients to arrive and put them into the lift. As soon the client enters the lift, the client also gets notified that it has entered the lift. The Lift also notifies the client when the top is reached.
Here is an example of how such solution could look like.
It uses the Java Executor Service to schedule the events for getting the client out of the lift and for reaching the lift station at the end oft the downhill part. This may also be solved differently.
The Client:
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Client implements Runnable{
final ScheduledExecutorService dhexceutors = Executors.newScheduledThreadPool(500);
final static Random DHRANDOM = new Random();
final long weight;
public enum State {
goDownhill,
waitForLift,
goUp,
onTop,
}
private State state;
public SkiLift lift;
public Client(long weight,SkiLift lift) {
this.lift = lift;
this.weight = weight;
this.state = State.onTop;
goDownHill();
}
private void enterLift() {
lift.add(this);
}
private void goDownHill() {
synchronized (this) {
state = State.goDownhill;
this.notify();
}
dhexceutors.schedule(() -> {
liftStationReached();
}, DHRANDOM.nextInt(500), TimeUnit.MILLISECONDS);
}
public void liftStationReached() {
synchronized(this) {
state = State.waitForLift;
this.notify();
}
}
public void topReached() {
synchronized(this) {
state = State.onTop;
this.notify();
}
}
public void liftEntered() {
synchronized(this) {
state = State.goUp;
this.notify();
}
}
public void run() {
synchronized(this) {
while (true) {
try {
this.wait();
switch (state) {
case waitForLift:
enterLift();
break;
case goUp:
// just wait for the topReached event
break;
case goDownhill:
// just wait for reaching the lift.
break;
case onTop:
goDownHill();
break;
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
}
The Lift:
package skilift;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class SkiLift implements Runnable{
private ScheduledExecutorService getOutClientExecutor;
public SkiLift() {
getOutClientExecutor = Executors.newScheduledThreadPool(50);
waitingClientsQueue = new ArrayBlockingQueue<>(1000);
occupiedSeats = new ArrayList<>();
}
private final ArrayList<Client> occupiedSeats;
private long usedCapacity;
private final ArrayBlockingQueue<Client> waitingClientsQueue;
private final long capacity = 500;
public void add(Client client) {
synchronized(waitingClientsQueue) {
waitingClientsQueue.add(client);
waitingClientsQueue.notify();
}
}
private synchronized void occupySeat(Client client) {
occupiedSeats.add(client);
usedCapacity += client.weight;
}
private synchronized void getClientOut(Client client) {
occupiedSeats.remove(client);
usedCapacity -= client.weight;
// notify the waitingClientQueue that the capacity has changed
synchronized (waitingClientsQueue) {
waitingClientsQueue.notify();
}
client.topReached();
}
public void run() {
while (true) {
synchronized(waitingClientsQueue) {
try {
if (!waitingClientsQueue.isEmpty()) {
Client c = waitingClientsQueue.peek();
if (usedCapacity + c.weight <= capacity) {
occupySeat(waitingClientsQueue.poll());
getOutClientExecutor.schedule(() -> {
getClientOut(c);
}, 2, TimeUnit.SECONDS);
} else {
waitingClientsQueue.wait();
}
} else {
waitingClientsQueue.wait();
}
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}
}
Apparently, the bottleneck in your system is the lift. You can only have N concurrent users of the lift.
Also, 3. mentions a Monitor. After some reading what a monitor is, you should figure out that it allows exclusive access to the limited resource, the lift.
So design your lift access to try to acquire one of the N monitors, wait a while, and at the end do not forget to release the monitor, so someone else can get it.

Stopping or Interrupting a Java Thread

I am trying to stop a java thread if it is running for 6000 milliseconds.
Below code to kill the Thread R1 is failed to stop the thread. could you please correct code?
I have tried this code with while (!Thread.currentThread().isInterrupted()) to stop the thread.
import java.time.Duration;
import java.time.Instant;
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
ThreadDemo(String name) {
threadName = name;
System.out.println("Creating " + threadName);
}
#Override
public void run() {
System.out.println("Running " + threadName);
try {
while (!Thread.currentThread().isInterrupted()) {
for (int i = 100; i > 0; i--) {
System.out.println("Thread: " + threadName + ", " + i);
// Let the thread sleep for a while.
Thread.sleep(600);
}
}
} catch (InterruptedException e) {
System.out.println("Thread " + threadName + " interrupted.");
Thread.currentThread().interrupt();
}
System.out.println("Thread " + threadName + " exiting.");
}
#Override
public void start() {
System.out.println("Starting " + threadName);
if (t == null) {
t = new Thread(this, threadName);
t.start();
}
}
}
public class Killthread {
public static void main(String args[]) throws InterruptedException {
Instant timeBefore = Instant.now();
ThreadDemo R1 = new ThreadDemo("Thread-1");
R1.start();
System.out.println("Afte thread start");
Thread.sleep(6001);
Instant timeAfter = Instant.now();
if (Duration.between(timeBefore, timeAfter).toMillis() > 6000) {
R1.interrupt();
// R1.stop();
System.out.println("Thread Interrupted due to Time limitation.");
}
}
}
You've got two problems in your code, firstly that you aren't sleeping your main thread long enough, and secondly that you're interrupting the wrong thread.
6001 ms isn't long enough to guarantee that your duration check will be true. When I run your code, the main method rarely enters the if block. If you change to it sleep for 6100 ms, it should consistently call the interrupt.
Your second problem is that you're interrupting R1, but you need to be interrupting t.
If you override interrupt() in ThreadDemo to pass the call down to t, then it will receive the interrupt and break its execution thread.
e.g.
#Override public void interrupt() {
t.interrupt();
}
The problem is, that you start a complete new, different and unnecessary thread in ThreadDemo::start.
#Override
public void start() {
System.out.println("Starting " + threadName);
if (t == null) {
t = new Thread(this, threadName);
t.start();
}
}
It should rather look like
#Override
public void start() {
System.out.println("Starting " + threadName);
super.start();
}
And get rid of that private Thread t; in ThreadDemo.
In please of calling t.start() from your overridden start method call super.start() which will call the start() of thread class, and is responsible to create new thread and register it with thread scheduler.

Java Semaphore Acquire Order Based on Thread Value

Good afternoon everyone,
I am working on a school project that requires me to use semaphores to control access to resources. From what I have developed so far, they are:
Semaphore 1) Waiting Area - This permits only 15 customers (Threads) to enter the waiting area, else they are rejected from the store (using TryAcquire).
Semaphore 2) ServerQueue - This permits customers (Threads) to use the only 3 servers in the restaurant once in the waiting area.
My Problem: Our professor requires the serverQueue to take the shortest order (IE, the thread with the least amount of burritosOrdered) when in the waitingArea.
Full flow of application:
Main method instantiates a serverQueue (3 servers) and a waitingArea (15 customers)
Main method instantiates and starts 20 customer threads
Each customer (Thread) run function has been overridden to attempt to get in the waiting area
Each customer in the waitingArea tries to access a server in the serverQueue
How can I tell the serverQueue to get the shortest order? Because the threads override the run, I don't have direct access to an array of all the threads to compare their values.
Thank you for taking a look!
Main
public class Main {
private static final int numCustomers = 5;
public static void main(String[] args)
{
ServerQueue serverQueue = new ServerQueue();
WaitingArea waitingArea = new WaitingArea(3, serverQueue);
Thread customers[] = new Thread[numCustomers];
for (int i = 0; i < numCustomers; i++)
{
customers[i] = new Thread(new Customer(waitingArea), "Customer " + i);
}
for (int i = 0; i < numCustomers; i++)
{
customers[i].start();
}
}
}
Customer
import java.util.Date;
import java.util.Random;
// Runnable is an interface that facilitates threads
public class Customer implements Runnable {
// The semaphore
// private ServerQueue serverQueue;
private WaitingArea waitingArea;
public int burritosOrdered;
public int burritosMade = 0;
// Constructor, allow semaphore to be passed/assigned
public Customer(WaitingArea waitingArea) {
this.waitingArea = waitingArea;
Random r = new Random();
this.burritosOrdered = r.nextInt(21);
}
public void setBurritosMade(int newBurritos) {
this.burritosMade += newBurritos;
}
// We must override the run function within Runnable
// The run function is called by threadObject.start();
#Override
public void run() {
waitingArea.seatCustomer(burritosOrdered);
}
}
waitingArea
import java.util.Date;
import java.util.concurrent.Semaphore;
public class WaitingArea {
private Semaphore semaphore;
private ServerQueue serverQueue;
private int maxCustomers;
public WaitingArea(int maxCustomers, ServerQueue serverQueue) {
semaphore = new Semaphore(maxCustomers, true);
this.serverQueue = serverQueue;
this.maxCustomers = maxCustomers;
}
public void seatCustomer(int burritosOrdered)
{
boolean hasPermit = false;
try
{
hasPermit = semaphore.tryAcquire();
if(hasPermit) {
System.out.println(new Date() + " - "
+ Thread.currentThread().getName()
+ " entered store ordering "
+ burritosOrdered + " burritos");
serverQueue.finishOrder();
} else {
System.out.println(new Date() + " - " + Thread.currentThread().getName() + " left due to full shop");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(hasPermit) {
semaphore.release();
System.out.println(new Date() + " - "
+ Thread.currentThread().getName()
+ " left with " + burritosOrdered + " burritos made");
}
}
}
}
serverQueue
import java.util.Date;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ServerQueue {
// This Semaphore will keep track of no. of servers used at any point.
private final Semaphore semaphore;
// While checking/acquiring a free server out of three available servers, we will use this lock.
private final Lock serverLock;
// This array represents the pool of free server.
private boolean freeServers[];
public ServerQueue() {
semaphore = new Semaphore(1, true);
freeServers = new boolean[1];
serverLock = new ReentrantLock();
// Set all servers to available
for(int i=0;i<freeServers.length;i++) {
freeServers[i] = true;
}
}
public void finishOrder() throws InterruptedException {
try {
System.out.println(semaphore.getClass());
// Decrease the semaphore counter to mark a printer busy
semaphore.acquire();
// Get the server printer
int assignedServer = getServer();
Thread.sleep(3000);
// Print the job
System.out.println(new Date() + " - " + Thread.currentThread().getName()
+ " is getting service from server " + assignedServer);
//Server is done; Free the server to be used by other threads.
releaseServer(assignedServer);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.print(new Date() + " - " + Thread.currentThread().getName() + " has been served\n");
//Increase the semaphore counter back
semaphore.release();
}
}
//Acquire a free server to finish a job
private int getServer() {
int foundServer = -1;
try {
//Get a lock here so that only one thread can go beyond this at a time
serverLock.lock();
//Check which server is free
for (int i=0; i<freeServers.length; i++)
{
//If free server found then mark it busy
if (freeServers[i])
{
foundServer = i;
freeServers[i] = false;
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//Allow other threads to check for free servers
serverLock.unlock();
}
return foundServer;
}
//Release the server
private void releaseServer(int i) {
serverLock.lock();
//Mark the server as free
freeServers[i] = true;
serverLock.unlock();
}
}

Categories