简体   繁体   中英

Balancing thread usage of CPU/memory resources on Java J2EE server

I am developing a website/online-service for document collaboration that runs on JBoss. During testing on a Linux machine with 2.5Ghz cpu and 2GB RAM the page response is very fast and we are considering to launch with this machine.

The problem arises during document processing. After a user uploads a document a new thread is started that among other things converts the document, extracts text and images from the document and uploads the document through https on another server. A user can upload many documents at once and the threads for processing them work concurrently. Until this processing finishes the website becomes almost unresponsive.

Can you give me some advice on how I could somehow allocate a percentage of CPU/memory (eg 40% max) on the threads that process the documents? If this is not possible, please advise me on a methodology/pattern that will somehow share the load on the machine between JBoss responding to page requests and the threads that process the documents.

Regards

There's not really a way to allocate a certain percentage of CPU/memory time for a given thread. You could lower the thread priority so it doesn't saturate all resources:

int oldPriority = Thread.currentThread().getPriority();
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
// process your documents here
Thread.currentThread().setPriority(oldPriority);

A better approach that will probably get you closer to specifying a percentage will be to use an ExecutorService with a fixed number of threads and run all of your document processing through that. If you give it half of the number of processors in your server then it'll effectively limit the document processing to 50% of the server CPU time. You'd want a singleton service that sets up a thread pool like this:

int threads = Runtime.getRuntime().availableProcessors() / 2;
ExecutorService service = Executors.newFixedThreadPool(threads);

Then in your web requests you could pass a Callable that implements your document processing to the service, and block until it is complete:

Callable<Result> callable = new DocumentProcessorCallable<Object>(doc);
Result result = service.submit(callable).get();

Or you might prefer to not block and return immediately by providing an implementation of Runnable that you pass to service.execute(runnable) . See ExecutorService for more examples and documentation.

After the user has submitted the documents, you could submit them all into a JMS Queue where only a single instance of an MDB is listening to. So document processing will be serial and thus only use one thread (which still could use a lot of CPU).

If this solution is not enough, you can put a remote MDB on a different server to process the documents, and basically offloading the document processing. Beauty here is that this change basically only is a configuration change and does not need recompiling your app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM