I'm writing a Java program which uses a lot of CPU because of the nature of what it does. However, lots of it can run in parallel, and I have made my program multi-threaded. When I run it, it only seems to use one CPU until it needs more then it uses another CPU - is there anything I can do in Java to force different threads to run on different cores/CPUs?
In short: yes, a thread can run on different cores.
In computer architecture, multithreading is the ability of a central processing unit (CPU) (or a single core in a multi-core processor) to provide multiple threads of execution concurrently, supported by the operating system. This approach differs from multiprocessing.
Superscalar means executing multiple instructions at the same time while thread-level parallelism (TLP) executes instructions from multiple threads within one processor chip at the same time.
You'd prefer multiple threads over multiple processes for two reasons: Inter-thread communication (sharing data etc.) is significantly simpler to program than inter-process communication. Context switches between threads are faster than between processes.
There are two basic ways to multi-thread in Java. Each logical task you create with these methods should run on a fresh core when needed and available.
Method one: define a Runnable or Thread object (which can take a Runnable in the constructor) and start it running with the Thread.start() method. It will execute on whatever core the OS gives it -- generally the less loaded one.
Tutorial: Defining and Starting Threads
Method two: define objects implementing the Runnable (if they don't return values) or Callable (if they do) interface, which contain your processing code. Pass these as tasks to an ExecutorService from the java.util.concurrent package. The java.util.concurrent.Executors class has a bunch of methods to create standard, useful kinds of ExecutorServices. Link to Executors tutorial.
From personal experience, the Executors fixed & cached thread pools are very good, although you'll want to tweak thread counts. Runtime.getRuntime().availableProcessors() can be used at run-time to count available cores. You'll need to shut down thread pools when your application is done, otherwise the application won't exit because the ThreadPool threads stay running.
Getting good multicore performance is sometimes tricky, and full of gotchas:
One other problem: controlling work is hard! A good practice is to have one manager thread that creates and submits tasks, and then a couple working threads with work queues (using an ExecutorService).
I'm just touching on key points here -- multithreaded programming is considered one of the hardest programming subjects by many experts. It's non-intuitive, complex, and the abstractions are often weak.
Edit -- Example using ExecutorService:
public class TaskThreader { class DoStuff implements Callable { Object in; public Object call(){ in = doStep1(in); in = doStep2(in); in = doStep3(in); return in; } public DoStuff(Object input){ in = input; } } public abstract Object doStep1(Object input); public abstract Object doStep2(Object input); public abstract Object doStep3(Object input); public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); ArrayList<Callable> tasks = new ArrayList<Callable>(); for(Object input : inputs){ tasks.add(new DoStuff(input)); } List<Future> results = exec.invokeAll(tasks); exec.shutdown(); for(Future f : results) { write(f.get()); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With