Here is my example but it does not execute. It's only working correctly for my first thread pool but the second thread pool was not run. Is it the correct way or not?
If it's correct, where did I make the mistake and if it's not, how do I implement multiple executor services?
In my example the save API executed successfully, and the book appointment method calls the book API successfully, but after the book API, the code does not execute and I'm wondering why.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyTestClass {
public static void main(String args[]) {
//Create class object
MyTestClass myObj = new MyTestClass();
// Create List A
List<String> a = new ArrayList<>();
a.add("Test1");
a.add("Test2");
a.add("Test3");
a.add("Test4");
//Create List B
List<String> b = new ArrayList<>();
b.add("Test1");
b.add("Test2");
b.add("Test3");
b.add("Test4");
b.add("Test5");
b.add("Test6");
b.add("Test7");
b.add("Test3");
b.add("Test4");
b.add("Test5");
b.add("Test6");
b.add("Test7");
//Call my method
myObj.myMethod(a, b);
}
//Multi-threading example in appointment book method execute first api but its not called the second api
void myMethod(List<String> listA, List<String> listB){
ExecutorService threadPool = Executors.newFixedThreadPool(listA.size());
List<Callable<Object>> tasks = new ArrayList<>();
for (String strA : listA) {
tasks.add(Executors.callable(new Thread() {
#Override
public void run() {
processA(strA);
}
}));
}
try {
//Execute first thread pool for save
threadPool.invokeAll(tasks);
} catch (InterruptedException e1) {
e1.printStackTrace();
System.out.println("Error while running threads");
}
threadPool.shutdown();
//Call book appointment api
bookAppointMent(listB);
}
//Book appointment
void bookAppointMent(List<String> listB) {
ExecutorService threadPool2 = Executors.newFixedThreadPool(listB.size());
List<Callable<Object>> tasks2 = new ArrayList<>();
for (String strB : listB) {
tasks2.add(Executors.callable(new Thread() {
#Override
public void run() {
// Add task
processB(strB);
}
}));
}
try {
//Execute thread pool2
threadPool2.invokeAll(tasks2);
} catch (InterruptedException e1) {
e1.printStackTrace();
System.out.println("Error while running threads");
}
//Shutdown pool-2
threadPool2.shutdown();
}
//Save appointment
public void processA(String a){
//Here its save API
System.out.println("Save A successfully...." + a);
}
//Book Appointment In this method only first api called but second one is not called
public void processB(String b){
//Here is First API call - This only called
System.out.println("Appointment booked successfully...." + b);
//Here is second API call - Its not called
processAfterAppBooked(b);
}
//Process after book app
public void processAfterAppBooked(String b) {
//Second api call - its not execute
System.out.println("After appointment booked " + b);
}
}
Related
Need help with code at below link as it should run indefinitely likewise with any typical producer/consumer problem but somehow it is getting stuck on call of condition.signal(). What am I doing wrong here?
In main method, I have created two thread, one is consumer and other one is producer. it has shared task queue where both updates the entry.
package com.anurgup.handson;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionService implements Runnable {
Lock lock = new ReentrantLock();
Condition added = lock.newCondition();
Condition removed = lock.newCondition();
// type of service
String type;
// shared task for insertion and deletion of task
static Queue<Integer> task = new PriorityQueue<Integer>();
// max number of task allowed
private static final int MAX_SIZE = 5;
public ConditionService(String type) {
this.type = type;
}
public static void main(String[] args) {
ExecutorService service = Executors.newFixedThreadPool(2);
service.submit(new ConditionService("producer"));
service.submit(new ConditionService("consumer"));
}
public void produce() {
try {
while (true) {
System.out.println("in producer...");
synchronized (task) {
while (task.size() == MAX_SIZE)
removed.await();
System.out.println("added item: " + task.size());
task.add(task.size());
added.signal();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void consume() {
try {
while (true) {
System.out.println("in consumer...");
synchronized (task) {
while (task.isEmpty())
added.await();
System.out.println("removed item: " + task.peek());
task.remove();
removed.signal();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void run() {
if (this.type.equals("producer"))
this.produce();
else
this.consume();
}
}
You're making two mistakes. First, your lock and conditions need to be static, or each task will only synchronize and wait on itself. Second, you need to use lock.lock(), not synchronized. It should look like this:
lock.lock();
try {
// wait
// produce/consume
} finally {
lock.unlock();
}
There are two thread, A Thread let the list add ten times, B Thread will quit when the list.size() > 5.I think the result should be "B would quit after A add 5, maybe 6,7,7,8,9",but the result is B never quit.
and the other question is when i add a line there, it would be ok! why?
package com.lock;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Create by #author Henry on 2018/5/4
*/
public class NoWait {
static volatile ArrayList list = new ArrayList();
public static void main(String[] args) throws InterruptedException {
ThreadA a = new ThreadA(list);
a.setName("A");
a.start();
ThreadB b = new ThreadB(list);
b.setName("B");
b.start();
Thread.sleep(10000);
System.out.println("A is " + a.isAlive());
System.out.println("B is " + b.isAlive());
}
}
class ThreadA extends Thread{
private ArrayList list;
public ThreadA(ArrayList list){
this.list = list;
}
#Override
public void run(){
try{
for (int i = 0; i < 10; i++) {
list.add(i);
System.out.println("=====================================add "+(i+1));
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("A finished");
}
}
class ThreadB extends Thread{
String s = "";
private ArrayList list;
public ThreadB(ArrayList list){
this.list = list;
}
#Override
public void run(){
try{
while(true){
//s += list.size();
//System.out.println(list.size());
if(list.size() > 5){
System.out.println(">5 now, B gonne quit");
throw new InterruptedException();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
the result is B Thread never stop! this is my first question.
the second is , when I add this line
//s += list.size();
//System.out.println(list.size());
and it will be ok, Why?!! how they works!
Thread B is not guaranteed to see any changes from thread A because there is no synchronization between them.
Volatile won't do anything here as it only ensures the reference to the list is visible to both threads but not updates to its contents.
The println has internal synchronization which causes the changes between the threads to be visible.
I want to have print server that outputs the requested messages to the computer screen as follows: Client threads invoke the printRequestV1 method to submit the messages (strings) to be output. But all the printRequestV1 method should do is place the message in the print job queue, and a separate (manager) thread then dequeues messages from the job queue and outputs them to the screen
I know that I need to synchronize the shared request queue and check whether the queue is not empty before trying to remove a message. If the queue is empty, the manager thread needs to wait until client threads add some messages, and the client thread, after adding a message, will let the manager thread know by signaling.
Here what I have so far:
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import static java.lang.System.out;
public class PrintServerV1 implements Runnable {
private static final Queue<String> requests = new LinkedList<String>();
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public PrintServerV1() {
try{
while(requests.size() != 0){ condition.await();}
new Thread(this).start();
}
catch (InterruptedException exception) {}
}
public void printRequest(String s) {
lock.lock();
try
{
out.println("Adding print request for: " +s);
requests.add(s);
condition.signalAll();
}
finally { lock.unlock(); }
}
public void sendRequest() throws InterruptedException
{
try {
while(requests.size() != 0){ condition.await();}
out.println("Sending Request to printer");
for(;;) realPrint(requests.remove());
} finally { lock.unlock(); }
}
private void realPrint(String s) {
// do the real work of outputting the string to the screen
out.println("Currently printing: " + s);
}
public void run(){
try{
sendRequest();
} catch (InterruptedException exception) {}
}
public static void main(String[] args){
PrintServerV1 server = new PrintServerV1();
server.printRequest("homework7.txt");
}
}
I am getting the following output:
Adding print request for: homework7.txt
Sending Request to printer
Currently printing: homework7.txt
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at PrintServerV1.sendRequest(PrintServerV1.java:43)
at PrintServerV1.run(PrintServerV1.java:54)
at java.lang.Thread.run(Thread.java:748)
My question is wouldn't it better if make two classes, one named manager who implements runnable and whose sole purpose is to remove from the queue and one class named client who implements runnable and whose purpose is to add requests to the queue?
You can only unlock after you aquire the lock by lock, otherwise IllegalMonitorStateException will be thrown. You should also call await method after you aquiring the lock.
It is a bad idea to await in the construtor, it will cause the creation of instance get blocked;
Remove the elements only when the requests is not empty.
This code works fine on my machine:
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
import static java.lang.System.out;
public class PrintServerV1 implements Runnable {
private static final Queue<String> requests = new LinkedList<String>();
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void printRequest(String s) {
lock.lock();
try {
out.println("Adding print request for: " + s);
requests.add(s);
condition.signalAll();
} finally {
lock.unlock();
}
}
public void sendRequest() throws InterruptedException {
lock.lock();
try {
while (requests.size() == 0) {
condition.await();
}
out.println("Sending Request to printer");
while (!requests.isEmpty()) {
realPrint(requests.remove());
}
} finally {
lock.unlock();
}
}
private void realPrint(String s) {
// do the real work of outputting the string to the screen
out.println("Currently printing: " + s);
}
public void run() {
try {
sendRequest();
} catch (InterruptedException exception) {
}
}
public static void main(String[] args) {
PrintServerV1 server = new PrintServerV1();
new Thread(server).start();
server.printRequest("homework7.txt");
}
}
Output:
Adding print request for: homework7.txt
Sending Request to printer
Currently printing: homework7.txt
I suggest to use two threads, one producer and one consumer, as well as a BlockingQueue to solve this kind of problem. The synchronization will be handled by the blocking queue, so you can focus on you business logic.
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
new Thread(new Producer(queue)).start();
new Thread(new Consumer(queue)).start();
}
}
class Consumer implements Runnable {
private LinkedBlockingQueue<String> queue;
public Consumer(LinkedBlockingQueue<String> queue) {
this.queue = queue;
}
#Override
public void run() {
while (true) {
String request;
try {
request = queue.take();
System.out.println(request);
} catch (Exception e) {
}
}
}
}
class Producer implements Runnable {
private LinkedBlockingQueue<String> queue;
public Producer(LinkedBlockingQueue<String> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
queue.put("homework7.txt");
} catch (Exception e) {
}
}
}
I'm creating a game and I'm stuck in this problem:
I have the class Game and inside the Game, I have the Kitchen.
When the player type for example: /new egg I do: game.kitchen.newEgg()
I would like to know what is the best way, and how I can notify the game that the Egg is finished.
I tried putting the class Game as static, but is doesn't seem correct.
I also tried every 1 second the game call kitchen.isReady() (neither this looks like correct)
and my last try was create a Consumer like this:
public class Kitchen {
public void newEgg(String name, Consumer<String> function){
System.out.println("egg is in progress");
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
function.accept(name);
}
}
and in the game:
public void createEgg(String eggName){
System.out.println("Creating an Egg");
Kitchen egg = new Kitchen();
Gamex x = new Gamex();
Runnable task2 = () -> { egg.newEgg(eggName, x::eggCreated); };
new Thread(task2).start();
System.out.println("game continue...");
}
public void eggCreated(String eggName) {
System.out.println("Egg: " + eggName + " finished.");
}
All the tree methods worked, but Is this the proper way to do?
How I should do it?
What is the best solution for a game?
Being notified that an asynchronous job is done would be a job for a CompletableFuture<V> (Java 8).
It is quite like a Future<V>, only you can attach to it additional callbacks that get triggered immediately when the job completes.
Here is a minimal working example that you could adapt to your game engine :
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Example {
public static void main(String[] args) {
Example example = new Example();
// Start generating a String
ExecutorService pool = Executors.newFixedThreadPool(4); // We need some pool to run things async
CompletableFuture.supplyAsync(example::createString, pool) // run the creation job in another thread
.thenAccept(example::callback); // run this callback when the job is done
pool.shutdown();
// Doing something else in the meantime...
System.out.println("Meandering...");
}
private String createString() {
artificialDelay();
return "Hello World";
}
private void callback(String input) {
System.out.println("Received this : " + input);
}
private void artificialDelay() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
how can I get in stop() thread names like i did in start()? Thread names are A,B,C,D. My program runs thread in order and stops them in revers order. But I have problem with printing their names. In start() I do it without any problems but in stop() I just dont know how to do it. I'm pretty new in java and this is one of my firs programs that I did that is why i dont know how to do this.
Thank you so much for your help.
Here is the code:
import java.util.*;
class Service extends Thread
{
private RobotController controller;
public String robotID;
private byte[] lock;
public Service(RobotController cntrl, String id)
{
controller = cntrl;
robotID = id;
}
public byte[] getLock() { return lock;}
public void run()
{
lock = new byte[0];
synchronized(lock)
{
byte[] data;
while ((data = controller.getData()) == null)
{
try {
lock.wait();
} catch (InterruptedException ie) {}
}
System.out.println("Thread " + robotID + " Working" );
}
}
}
class RobotController
{
private byte[] robotData;
private Vector threadList = new Vector();
private Service thread_A;
private Service thread_B;
private Service thread_C;
private Service thread_D;
public void setup(){
thread_A = new Service(this, "A");
thread_B = new Service(this, "B");
thread_C = new Service(this, "C");
thread_D = new Service(this, "D");
threadList.addElement(thread_A);
threadList.addElement(thread_B);
threadList.addElement(thread_C);
threadList.addElement(thread_D);
thread_A.start();
thread_B.start();
thread_C.start();
thread_D.start();
start();
stop();
}
public void start()
{
System.out.println("START:");
{
for (int i=0; i <threadList.size(); i++)
{
try {
Thread.sleep(500);
}catch (InterruptedException ie){
System.out.println(ie);
}
putData(new byte[10]);
Service rbot = (Service)threadList.elementAt(i);
byte[] robotLock = rbot.getLock();
synchronized(robotLock) {
robotLock.notify();
}
}
}
}
public void stop()
{
Collections.reverse(threadList);
System.out.println("STOP:");
for ( Object o : threadList) {
System.out.println("Thread "+ o +" Stop");
}
}
public synchronized byte[] getData()
{
if (robotData != null)
{
byte[] d = new byte[robotData.length];
System.arraycopy(robotData, 0, d, 0, robotData.length);
robotData = null;
return d;
}
return null;
}
public void putData(byte[] d) { robotData = d;}
public static void main(String args[])
{
RobotController controller = new RobotController();
controller.setup();
}
}
Thread has name and getter getName(), so if you have instance of thread you can always call thread.getName().
I do not know how do you access the thread name "in start" because I do not see where do you call getName(). However I think I know what's your problem in stop.
You store your threads in Vector. Then you iterate over vector's elements and print thread, so it invokes thread's toString(). You probably have to cast Object to Thread and call its getName():
System.out.println("STOP:");
for ( Object o : threadList) {
System.out.println("Thread "+ ((Thread)o).getName() +" Stop");
}
But once you are done, I'd recommend you to find a good and new enough tutorial on java.
You are using not commonly applicable coding formatting.
You are using Vector instead of List and its implementations.
You are trying to use unclear technique for thread synchronization and management.
Start learning step-by-step. And do not hesitate to ask questions. Good luck.