The output of the following simple code is a little odd to me.
it miss out some of the numbers between 0 and 100 to print on the console.
could anyone explain why it omit to print? i am completely new to concurrency programming.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
public class SimpleTest {
#Test
public void testSimple() throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i = 0; i <= 100; i++) {
executorService.execute(new SimpleRunnable(i));
}
executorService.shutdown();
}
}
class SimpleRunnable implements Runnable {
int i;
public SimpleRunnable(int i) {
this.i = i;
}
public void run() {
synchronized(System.out) {
System.out.println(i);
}
}
}
You should wait for the executor service to finish after calling shutdown
executorService.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS); // Wait for the tasks to finish.
// and flush!
System.out.flush();
I suspect the threads created are daemon threads, which do not prevent a JVM shutdown. Since the threads are kicked off and forgotten, after your call to shutdown, the method returns and then the JVM exits because there is nothing else to do. Unfinished work never gets done.
As Elliot pointed out, use the awaitTermination method:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long, java.util.concurrent.TimeUnit)
Related
Simply put, i'm trying to see the difference when using sychronized keyword over just running a function over threads without locks at all.
In this code:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
public class mainClass {
static int count=0;
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
Runnable r =new Runnable() {
public synchronized void run() {
count = count + 1;
}
};
IntStream.range(0, 10000)
.forEach(i -> executor.submit(r::run));
executor.shutdown();
System.out.println(count); // 10000
}
}
It doesn't work as i predicated it to work, it returns 10000 in like 40% of the runs. Why is that? Where is the problem?
I thought that the function run is being run by only 1 Thread at a time, so there shouldn't be problem, but clearly i'm wrong.
ExecutorService#shutdown does not wait for tasks to complete. You should use awaitTermination for that.
See the documentation for ExecutorService#shutdown.
IntStream.range(0, 10000)
.forEach(i -> executor.submit(r::run));
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTE); // <!-- HERE
So I'm making an emulator for an online game and I can't seem to think of a good way to deal with lots of tasks running simultaneously. Loading everything on a single thread just doesn't work, obviously.
My idea was to have a main thread that delegates tasks to x amount of worker threads. Once the main thread is done queueing tasks, it signals the workers to start firing tasks and halts untill they have finished. My implementation is as follows:
package com.rs2.engine;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.CountDownLatch;
import java.util.ArrayList;
import com.rs2.util.Timer;
public class Engine implements Runnable {
private ScheduledExecutorService scheduledExecutorService;
private ExecutorService executorService;
private int currentTick;
private ArrayList<Task> tasks;
private Timer timer;
public Engine(int workers) {
this.executorService = Executors.newFixedThreadPool(workers);
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
this.currentTick = 0;
this.tasks = new ArrayList<>(10000);
this.timer = new Timer();
}
public int getCurrentTick() {
return currentTick;
}
public ExecutorService getWorkers() {
return executorService;
}
public void start() {
this.scheduledExecutorService.scheduleAtFixedRate(this, 0, 600, TimeUnit.MILLISECONDS);
}
public void cycle() {
}
public void queueTask(Task task) {
tasks.add(task);
}
public void processQueuedTasks() {
try {
CountDownLatch latch = new CountDownLatch(tasks.size());
for (int i = 0; i < tasks.size(); i++) {
Task t = tasks.get(i);
t.setCountDownLatch(latch);
executorService.submit(t);
}
latch.await();
tasks.clear();
} catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void run() {
timer.reset();
cycle();
currentTick++;
//System.out.println("Cycle time: "+timer.elapsed());
}
}
queueTask() and processQueuedTasks() are only called from the main thread. This Engine is used to deal with any and all tasks that the server needs executing. First it processes networking events (incoming packets), then updating entities and other events. That's why I like to keep it abstract.
Here's the Task class aswell:
package com.rs2.engine;
import java.util.concurrent.CountDownLatch;
public class Task implements Runnable {
private CountDownLatch latch;
public Task() {
}
#Override
public void run() {
execute();
latch.countDown();
}
public void execute() {
}
public void setCountDownLatch(CountDownLatch latch) {
this.latch = latch;
}
}
My questions are as follows:
In the Engine class, is it OK to work with a regular ArrayList in terms of concurrency?
Is there a better way of queueing tasks to the ExecutorService? I feel like it might cause issues if too many tasks are queued to it at the same time.
Are there any engine frameworks I should be looking at before I start reinventing the wheel?
If you are worried that you might be queueing too much tasks in the ExecutorService you can use Semaphore to limit the tasks it can run at a time.
Put it in your processQueuedTasks() method for loop to limit the number of tasks to be run.
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html
Instead of using a Semaphore to throttle the number of tasks run concurrently, you could set the number of threads in the threadpool. You will only get as many tasks running concurrently as you have threads
Executors.newFixedThreadPool(n);
public void queueTask(Task task) {
As this method is public, it can be called from any thread and so the ArrayList would not be thread safe. Think about what would happen if you tried to queue a task during the time they are submitted to the executor. You have 'borrowed' functionality from a thread pool executor and placed it in your code by having the collection for tasks.
I have the following piece of code which I expected to print "DONE" at the end. But when I ran, "DONE" was never printed and the JVM in fact never terminated.
What did I do wrong?
// File: Simple.java
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Simple {
public static void main(String[] args) throws Exception{
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
Thread[] runnables = new Thread[times];
for (int i = 0; i < runnables.length; ++i) {
runnables[i] = new Thread(new MyRunnable());
}
// schedule for them all to run
for (Thread t : runnables) {
tp.schedule(t, 1, TimeUnit.SECONDS);
}
try {
tp.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
System.out.println("DONE!");
}catch (InterruptedException e) {
e.printStackTrace();
}
}
static class MyRunnable implements Runnable {
#Override
public void run() {
System.out.println("hello world");
}
}
}
There are two things that you're doing wrong here.
First off, if you're using an ExecutorService, you shouldn't then also be creating your own threads. Just submit Runnables to the executor directly - the executor service has its own collection of threads, and runs anything you submit on its own threads, so the threads you created won't even get started.
Second, if you're done with an ExecutorService, and are going to wait until it's terminated, you need to call shutdown() on the executor service after you submit your last job.
Executors.newScheduledThreadPool(times) uses Executors.defaultThreadFactory() for its ThreadFactory.
Here is the documentation
When a Java Virtual Machine starts up, there is usually a single
non-daemon thread (which typically calls the method named main of some
designated class). The Java Virtual Machine continues to execute
threads until either of the following occurs:
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception
that propagates beyond the run method.
So, here is what you had; but I changed 3 things.
Added the shutdown hook
Made the schedule delayed by an extra second for each to demo that the shutdown is being called even before some of the threads are being called to run by the scheduler.
Lastly, you were telling it to wait forever using the Long.MAX. But I think you were doing it because the shutdown feels like it would shutdown now. But it won't.
public static void main(String[] args) throws Exception {
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
Thread[] runnables = new Thread[times];
for (int i = 0; i < runnables.length; ++i) {
runnables[i] = new Thread(new MyRunnable());
}
// schedule for them all to run
int i = 1;
for (Thread t : runnables) {
tp.schedule(t, i++, TimeUnit.SECONDS);
}
System.out.println("Calling shutdown");
tp.shutdown();
}
static class MyRunnable implements Runnable {
#Override
public void run() {
System.out.println("hello world");
}
}
Hope that answers your question. Now, you're kinda duplicating stuff.
If you are going to use the executerservice, you should just tell it to schedule stuff for you.
public static void main(String[] args) throws Exception {
doTest(3);
}
private static void doTest(final int times) {
ScheduledExecutorService tp = Executors.newScheduledThreadPool(times);
for (int i = 0; i < times; ++i) {
tp.schedule(new MyRunnable(), 1, TimeUnit.SECONDS);
}
System.out.println("Calling shutdown");
tp.shutdown();
}
static class MyRunnable implements Runnable {
#Override
public void run() {
System.out.println("hello world");
}
}
You forgot to shutdown your ExecutorService:
tp.shutdown(); // <-- add this
tp.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
Also I should mention that creating Threads to use them as Runnables is not only meaningless, but can be misleading as well. You should really use Runnable instead of Thread for runnables variable.
Runnable[] runnables = new Runnable[times];
Listed below is example code that I found for using the java.util.concurrent.ExecutorService. The main class includes a shutdown() method that calls the shutdown() method on the ExecutorService. What I do not understand from this example is when this method would be invoked.
Thanks.
package multithreadingexample;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MultithreadingExample {
ExecutorService executor = Executors.newFixedThreadPool(3);
public void start() throws IOException {
int i=0;
while (!executor.isShutdown())
executor.submit(new MyThread(i++));
}
public void shutdown() throws InterruptedException {
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);
executor.shutdownNow();
}
public static void main(String argv[]) throws Exception {
new MultithreadingExample().start();
}
}
class MyThread implements Runnable {
private final int i;
MyThread(int i) {
this.i = i;
}
#Override
public void run() {
System.out.println("I am in thread:"+i);
}
}
Why it is there:
To provide a way to shut down the ExecutorService to stop it from running tasks and to free the threads that it is using.
How it gets called:
You need to call it when you are done using the ExecutorService. In the example code you provided it is not called anywhere.
From the documentation:
The shutdown() method will allow previously submitted tasks to execute
before terminating, while the shutdownNow() method prevents waiting
tasks from starting and attempts to stop currently executing tasks.
Pardon me if the question sounds silly - I am just starting to use Executor.
I have an existing java app that uses threads in this manner-- basically standalone threads are used--
private Thread spawnThread( )
{
Thread t = new Thread()
{
String taskSnap = task.toString();
public void run()
{
try
{
println( task.run( null ) );
}catch( InterruptedException e )
{
println( "ITC - " + taskSnap + " interrupted " );
}
}
};
return t;
}
As you can see from above, the function returns a new thread.
Now in the main() function of the program, a new thread is created in this manner--
taskThread = spawnThread();
taskThread.start();
What i want to do is, create an executor service (with fixed number of threads)--> and then hand off creation of new thread/execution of task by the new thread to that executor.
As I am very new to Executor, what I wish to know is, how do I change the above code so that instead of a new separate thread being formed, a new thread is instead created within the thread pool. I cannot see any command to create a thread (within the thread pool)--> hand off the above task to that thread (and not to a stand-alone thread as above).
Please let me know how to resolve this problem.
In your main, you can write something like this:
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
executor.submit(new Runnable() {
String taskSnap = task.toString();
public void run() {
try {
println(task.run(null));
} catch( InterruptedException e) {
println("ITC - " + taskSnap + " interrupted ");
}
}
});
The submit method will execute the Runnable on one of the threads within the executor service.
Note: Don't forget to shutdown the executor service when you don't need it any more or it will prevent your program from exiting.
Do your research before asking. The idea is to create a class which implements Runnable and execute it using executor service.
Example from: Java Concurrency (Multithreading) - Tutorial
Implementation of the worker (which implements Runnable):
package de.vogella.concurrency.threadpools;
/** * MyRunnable will count the sum of the number from 1 to the parameter * countUntil and then write the result to the console. * <p> * MyRunnable is the task which will be performed * * #author Lars Vogel * */
public class MyRunnable implements Runnable {
private final long countUntil;
MyRunnable(long countUntil) {
this.countUntil = countUntil;
}
#Override
public void run() {
long sum = 0;
for (long i = 1; i < countUntil; i++) {
sum += i;
}
System.out.println(sum);
}
}
How to use executor service to run trigger the worker thread.
package de.vogella.concurrency.threadpools;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
private static final int NTHREDS = 10;
public static void main(String[] args) {
//You can also use Executors.newSingleThreadExecutor() if you just need 1 thread
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
for (int i = 0; i < 500; i++) {
Runnable worker = new MyRunnable(10000000L + i);
executor.execute(worker);
}
// This will make the executor accept no new threads
// and finish all existing threads in the queue.
executor.shutdown();
// Wait until all threads are finish
//while (!executor.isTerminated()) {
//}
//System.out.println("Finished all threads");
//All the threads might not be finished at this point of time. Thread endtime purely depends on the time taken by the processing logic inside your thread.
}
}
You mean something like this?
class Parallel {
private ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public void shutdown() {
pool.shutdown();
}
public void foo() {
pool.submit(new Runnable() {
#Override
public void run() {
// put your code here
}
});
}
}