I am currently trying to get my code to print what is in the method of simpleTask 20 times using the code in simpleTesting. The idea is that simpleTesting adds 20 instances of simpleTask to a queue then they are taken from the queue in simplePoolThread. What should happen is that it prints out the testing message 20 times then continues to run while looking for more things from the queue (but there are none). Instead it is currently just not printing anything and continuously running. Here is my code (a lot of it is interfaces, I believe the problem lies in the simpleThreadPool code):
package simpleThreadPool;
/**
* <<-- Pool Thread -->>
*
* It will be running continuously. It will try to retrieve new tasks when it is idle.
*/
public interface ISimplePoolThread extends Runnable {
/**
* Use an infinite loop to retrieve and perform tasks.
*/
#Override
public void run();
}
.
package simpleThreadPool;
/**
* <<-- Simple Task -->>
*
* ISimpleTask is to be performed by PoolThread.
*/
public interface ISimpleTask{
/**
* #1. Create a class to implement ISimpleTask, put content of the task to method run().
*/
public void run();
}
.
package simpleThreadPool;
/**
* <<-- Thread Pool -->>
* It manages a queue of tasks, starts some pool threads.
*
* #1. Create a task queue by using queue data structures, or designing your own data structure.
*/
public interface ISimpleThreadPool {
/**
* #1. Initialize your queue (or do so in somewhere)
* #2. Starts some ISimplePoolThreads.
*/
public void start();
/**
* #1. Stops everything
*/
public void stop();
/**
* #1. Add a task to your queue.
*/
public void addTask(ISimpleTask task);
}
.
package simpleThreadPool;
public class SimpleTask implements ISimpleTask {
#Override
public void run() {
System.out.println("testing testing 1 2 3");
}
}
.
I think the problem lies in this piece of code, where the tasks are taken from the queue:
package simpleThreadPool;
import java.util.concurrent.LinkedBlockingQueue;
public class SimplePoolThread implements ISimplePoolThread, Runnable {
private LinkedBlockingQueue<ISimpleTask> queue = new LinkedBlockingQueue<>();
#Override
public void run() {
while(true) {
System.out.println("Inserting Element: ");
try {
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
.
package simpleThreadPool;
import java.util.concurrent.LinkedBlockingQueue;
public class SimpleThreadPool implements ISimpleThreadPool {
private LinkedBlockingQueue<ISimpleTask> queue = new LinkedBlockingQueue<>();
#Override
public void start() {
(new Thread(new SimplePoolThread())).start();
}
#Override
public void stop() {
try {
queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void addTask(ISimpleTask task) {
try {
queue.put(task);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
.
the testing file:
package simpleThreadPool;
public class SimpleTesting implements ISimpleTask{
private int i;
public SimpleTesting(int i){
this.i = i;
}
#Override
public void run() {
System.out.println(i);
}
public static void main(String args[]){
// Initialize thread pool
SimpleThreadPool pool = new SimpleThreadPool();
pool.start();
// Create 20 tasks
for(int i = 1; i<=20; i++){
pool.addTask(new SimpleTesting(i));
}
}
}
The task queue in your SimplePoolThread is a blocking queue. As soon as it starts it executes queue.take(). Take is a blocking operation. The thread sits there waiting forever until something else adds a task into the queue.
Your hunch on the problem location was pretty close. The issue is that the queue in SimplePoolThread and the queue in SimpleThreadPool are not the same; you have two separate queues. So when SimpleTesting adds tasks they go into Pool's queue and NOT into the Thread's queue. So the thread will sit there forever waiting on nothing. You also forgot to actually run your tasks inside of SimplePoolThread.
Try the following instead.
public class SimpleThreadPool implements ISimpleThreadPool {
private LinkedBlockingQueue<ISimpleTask> queue = new LinkedBlockingQueue<>();
#Override
public void start() {
(new Thread(new SimplePoolThread(queue))).start();
}
Note that the queue from the pool was passed into the thread. The thread then keeps a reference to this queue. During the thread's run() it now also actually runs the task.
public class SimplePoolThread implements ISimplePoolThread, Runnable {
private LinkedBlockingQueue<ISimpleTask> queue;
public SimplePoolThread(LinkedBlockingQueue<ISimpleTask> queue)
{
this.queue = queue;
}
#Override
public void run() {
while(true) {
System.out.println("Inserting Element: ");
try {
ISimpleTask task = queue.take();
task.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Here's the output:
Inserting Element:
1
Inserting Element:
2
Inserting Element:
3
..etc..
I assume this is for homework otherwise I would tell you not to reinvent the wheel and go use Java's built-in pooling services.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html
Related
I am new to using threads. In another class an instance of the ConnectionMaster class is created and started (extends thread). A Client object is given to the ConnectionMaster object which adds it to the list. The overridden run() method of the Thread class essentially listens for a client to be added to the list. Indeed it does listen and "hears" when a Client object is added to the list. However, although .hasNext() returns true .Next() causes an exception. What am I doing wrong?
The following methods are from class ConnectionMaster which extends Thread:
Constructor
public ConnectionMaster(){
clients = new Vector<>();
listIterator = clients.listIterator();
}
Public method for adding client objects to the list
#Override
public synchronized void addClient(Client client) {
listIterator.add(client);
}
This is the overridden thread method of the class Thread. It consistently checks for elements added to the list.
#Override
public void run(){
while(true){
while(listIterator.hasNext()){
processClient(listIterator.next()); //this is where error occurs
listIterator.remove();
}
while(listIterator.hasPrevious()){
processClient(listIterator.previous());
listIterator.remove();
}
}
}
////////////////////////////////UPDATE////////////////////////////////////
Thank You OldCurmudgeon and Stephen C.
Based on your feedback, my code has been modified thus:
Constructor
public ConnectionMaster(){
clients = new ArrayBlockingQueue<Client>(1024);
}
Method for receiving client objects
#Override
public synchronized void addClient(Client client) {
try {
clients.put(client);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Listener
#Override
public void run(){
while(true){
try {
processClient((Client)clients.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This is a very strange way to implement Producer/Consumer. The usual way is to use a BlockingQueue.
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
try {
Integer i = queue.take();
ended = i == End;
System.out.println(i);
} catch (InterruptedException ex) {
ended = true;
}
}
}
}
public void test() throws InterruptedException {
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
What am I doing wrong?
Quite a lot actually.
First thing you are doing wrong is (apparently) using an ListIterator object in multiple threads. The ListIterator and Iterator implementations for Vector are not thread-safe1, so what you are doing is potentially hazardous.
The second thing is that even if the iterators / list iterators were thread-safe, you are performing a sequence of operations (e.g. hasNext, next, remove) without doing anything to ensure that the sequence of operations is performed in a way that is threadsafe. There is a distinct possibility that two threads could be performing the same sequence simultaneously on the shared iterator, and that one could interfere with the other.
I'm not sure what to suggest in order to fix your code. Two threads sharing an iterator is not going to work.
It would probably be better to ditch it, and use some kind of Queue as suggested by #OldCurmugeon.
Either problem 1 or problem 2 (as outlined above) could give rise to NoSuchElement exceptions.
1 - This is apparent from examining the source code - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Vector.java#Vector.ListItr .
My task here is to perform unzip operation using multiple threads. I did it with following structure Way.
// A class for Unzipping files
public class UnzipClass extends Thread(){
private String zipfile;
private Thread t;
public UnzipClass(String zipFile){
this.zipFile = zipFile;
}
public String getZipFile() {
return zipFile;
}
public void setZipFile(String zipFile) {
this.zipFile = zipFile;
}
public void run() {
try {
unzipFolder(this.getZipFile());
} catch (IOException ex) {
Logger.getLogger(Unzipper.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void start(String filename){
if (t == null){
t = new Thread(this,filename);
t.start();
}
}
public unzipFolder(String zipFile) throws ZipException, IOException
// Here is the Unzip Method
}
}
// Now I am calling this class from another class
public static void main(){
Thread t1 = new UnzipClass("filename1");
t1.start();
if(!(t1.isAlive())){
logEvent("Unzip Complete");
}
// Similarly I have Thread t2 with another file name
}
The above code works perfect and unzips the files but I have following problems.
I wanted to use implements Runnable , but I cannot use it because I did not find a way to pass variable(Filename) to another class which implements Runnable and do it. Literally: How to implement Runnable instead of extends Thread`
Using above method, How can I detect if the unzip process has been completed. To be specific how to stop the thread when the file unzip process is completed`.
Any sort of hint or solution would be really great.
Thanks in advance.
1.change
public class UnzipClass extends Thread
into
public class UnzipClass implements Runnable
and use
Runnable t1 = new UnzipClass("filename1");
to create the thread.
2.
use a while loop here
while((t1.isAlive())){
logEvent("Unziping...");
}
logEvent("Unzip Complete");
but using a flag like boolean isComplete in the UnzipClass will me more effective. like
in class UnzipClass add
private boolean complete=false;
then,
public void run() {
try {
unzipFolder(this.getZipFile());
complete=true;
} catch (IOException ex) {
Logger.getLogger(Unzipper.class.getName()).log(Level.SEVERE, null, ex);
}
}
//simple getter.
public boolean isComplete()
{
return this.complete;
}
in main...
while(!t1.isComplete()){
logEvent("Unziping...");
}
logEvent("Unzip Complete");
Just change extends Thread to implements Runnable.
While creating new thread, you will do
Thread t1 = new Thread(new UnzipClass("filename1"));
Instead of
Thread t1 = new UnzipClass("filename1");
As you want to unzip couple files simultaniously, try using ExecutorService for that. You can submit Runnable taks to be executed by thread pool - this way, you will reuse already existing threads.
Check Executors and ExecutorService
Please, check this solution.
It uses Java 8 features, but it can be easily upgraded to be used with Java 5 / 6 / 7 (and external library, like Apache Commons or Guava).
/**
* File unzipping service
*/
public class Unzipper {
/**
* Default number of threads
*/
private static byte DEFAULT_THREADS_COUNT = 5;
/**
* Completion handler
*/
private Consumer onComplete;
/**
* Unzipping tasks
*/
private Collection<File> unzippingTasks = new LinkedList<>();
/**
* Add task for unzipping file
*
* #param file Path to file to be unzipped
* #return upgraded <code>this</code> instance
*/
public Unzipper unzip(String file) {
//check validity of 'file' string: non-null and non-empty
//check that file pointed by 'file' exists
unzippingTasks.add(new File(file));
return this;
}
/**
* Add unzipping completion handler
*
* #param onComplete Unzipping completion handler
* #return upgraded <code>this</code> instance
*/
public Unzipper onComplete(Consumer onComplete) {
//check validity of 'onComplete' object: non-null
this.onComplete = onComplete;
return this;
}
/**
* Run files unzipping (with default number of threads)
*/
public void run() {
run(DEFAULT_THREADS_COUNT);
}
/**
* Run files unzipping
*
* #param threads Number of parallel threads
*/
public void run(byte threads) {
//check validity of 'threads' argument: non-negative and non-zero
//check that we have at least one 'unzipping' task
if(unzippingTasks.isEmpty()) {
//output to log that unzipping tasks list is empty
return;
}
CountDownLatch latch = new CountDownLatch(threads);
Executor executor = Executors.newFixedThreadPool(threads + 1); //we are not blocking in 'run' method, so we should create extra thread to wait for all tasks completion
for(File file: unzippingTasks) {
executor.execute(() -> {
//unzip file
latch.release();
});
}
executor.execute(() -> {
latch.await(); //wait for all unzipping tasks completion
if(onComplete) //you can use 'optional' here instead
onComplete.accept(null);
});
executor.shutdown();
}
}
....
//Usage example
new Unzipper()
.unzip("<path-to-some-file>")
.unzip("<path-to-another-file>")
.unzip("<path-to-some-another-file>")
.onComplete(() -> {
//make you log output
})
.run();
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipException;
public class UnzipClass {
// Now I am calling this class from another class
public static void main() {
Thread t1 = new Thread(new UnzipClassRunner("filename1"));
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class UnzipClassRunner implements Runnable {
private String zipfile;
public UnzipClassRunner(String zipFile) {
this.zipfile = zipFile;
}
public void run() {
try {
unzipFolder(zipfile);
} catch (IOException ex) {
Logger.getLogger(Unzipper.class.getName()).log(Level.SEVERE, null,
ex);
}
}
public void unzipFolder(String zipFile) throws ZipException, IOException {
//
}
}
Intellij IDEA is complaining about Generic array creation
public abstract class BaseImageLoader<CacheItem>
{
private ImageLoaderThread[] workerThreads;
public BaseImageLoader(Context context)
{
...
workerThreads = new ImageLoaderThread[DEFAULT_CACHE_THREAD_POOL_SIZE];//Generic array creation error
...
}
}
ImageLoaderThread is in fact a subclass of java.lang.Thread, its not generic
I dont get what im doing wrong
this works fine:
Thread[] threads = new Thread[DEFAULT_CACHE_THREAD_POOL_SIZE];
ImageLoaderThread class
private class ImageLoaderThread extends Thread
{
/**
* The queue of requests to service.
*/
private final BlockingQueue<ImageData> mQueue;
/**
* Used for telling us to die.
*/
private volatile boolean mQuit = false;
/**
* Creates a new cache thread. You must call {#link #start()}
* in order to begin processing.
*
* #param queue Queue of incoming requests for triage
*/
public ImageLoaderThread(BlockingQueue<ImageData> queue)
{
mQueue = queue;
}
/**
* Forces this thread to quit immediately. If any requests are still in
* the queue, they are not guaranteed to be processed.
*/
public void quit()
{
mQuit = true;
interrupt();
}
#Override
public void run()
{
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
ImageData data;
while (true)
{
try
{
// Take a request from the queue.
data = mQueue.take();
}
catch (InterruptedException e)
{
// We may have been interrupted because it was time to quit.
if (mQuit)
{
return;
}
continue;
}
...
//other unrelated stuff
}
}
}
I have an apllication where there are three folders. I am trying to implement the producer consumer concept using LinkedBlockingQueue.
Folder 1:
Contains a class which has a shared queue
public static BlockingQueue sharedQueue = new LinkedBlockingQueue();
From a method in this class I try to call the Producer thread and the Consumer thread both of which reside in separate files.
Thread updateThread = new Thread(new Producer(sharedQueue));
Thread takeThread = new Thread(new Consumer(sharedQueue));
updateThread.start();
takeThread.start();
Folder 2:Contains the producer thread class as follows:
public class Producer implements Runnable {
private final BlockingQueue Queue;
public Producer(BlockingQueue sharedQueue){
Queue = sharedQueue;
}
public void run()
{
while (Thread.currentThread() != null) {
Random random = new Random();
int pos = random.nextInt(productList.size());
String query = "insert into tab1 values("+pos+")";
Queue.put(query);
}
}
Folder 3: Contains the consumer class as follows:
public class Consumer implements Runnable{
private final BlockingQueue queue;
Collection<String> joblist;
public Consumer (BlockingQueue sharedQueue) {
queue = sharedQueue;
MonitoringForm.txtInforamtion.append("hi"+sharedQueue.size());
joblist = new ArrayList<String>();
}
#Override
public void run() {
while(true){
try {
for(int i = 0; i < queue.size(); i++)
{
joblist.add(queue.take().toString());
MonitoringForm.txtInforamtion.append("What we got "+queue.take().toString());
}
} catch (InterruptedException ex) {
Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
}
try {
Thread.sleep(60*1000);
} catch (Exception e) {
}
}
}
}
Can somebody tell me how to make sure that the data added to the shared queue by Producer class can be taken by Consumer class. The consumer consumes the data every minute. Not necessary that data is consumed as soon as it is produced. Calling the Consumer and Producer threads is not working as I have them in separate directories. Do I have to use remote method invocation? Is it possible for threads?
Here's a sample code I wrote which can help you understand the concept:
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* We want a Producer thread to create random values, and the Consumer thread to
* consume it. One caveat is that if the Producer has already created a random
* value, which the Consumer thread hasn't consumed yet, the Producer thread
* blocks or waits. On the flip side, the Consumer thread waits for the Producer
* thread to produce some value if the Producer thread hasn't already.
*
* Write a program to simulate such a situation.
*/
public class ProducerConsumerCommunication
{
private volatile boolean running = true;
private ArrayBlockingQueue<Integer> buffer = new ArrayBlockingQueue<>(1);
private Random random = new Random(System.currentTimeMillis());
private class ProducerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = random.nextInt();
buffer.put(value); // Blocks if buffer is full.
System.out.println("Value Put: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
private class ConsumerTask implements Runnable
{
public void run()
{
while (running)
{
try
{
Thread.sleep(random.nextInt(2000));
Integer value = buffer.take(); // Blocks if buffer is empty.
System.out.println("Value Taken: " + value);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
public ProducerConsumerCommunication()
{
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new ProducerTask());
service.execute(new ConsumerTask());
service.shutdown();
}
public static void main(String[] args)
{
new ProducerConsumerCommunication();
}
}
In the traditional Consumer/Producer concept the Consumer waits on a resource. And whenever the Producer pushes anything on the Queue it notifies the Consumer via notify() / notifyAll()
Producer :
queue.put(query) ;
obj.notifyAll();
Consumer :
while(true)
{
try {
obj.wait();
}catch (InterruptedException e) {
}
// get data from Queue
data = queue.take();
}
Refer to the following link for more information : example
To run the Producer and Consumer in the fashion like when the Producer produces something in the queue he should Notify the Consumer, and when the Consumer consumed from the queue he should notify to the Producer to produce something in the queue,
To implement your problem in that way you have to use
wait and Notify method if you have one producer and one consumer.
and if you have multiple consumer then you have to use NotifyAll method as well of Object Class,
And in your Consumer if you get this line printed to your console "What we got" then you are sure that Consumer has consumed something from the queue
I have a bunch of threads running concurrently. Sometimes a thread needs to notify other threads to wait for it to finish a job and signal them again to resume. Since I'm somehow new to Java's synchronization, I wonder what is the right way to do such thing. My code is something like this:
private void Concurrent() {
if (shouldRun()) {
// notify threads to pause and wait for them
DoJob();
// resume threads
}
// Normal job...
}
Update:
Note that the code I wrote is inside a class which will be executed by each thread. I don't have access to those threads or how they are running. I'm just inside threads.
Update 2:
My code is from a crawler class. The crawler class (crawler4j) knows how to handle concurrency. The only thing I need is to pause other crawlers before running a function and resume them afterwards. This code is the basics of my crawler:
public class TestCrawler extends WebCrawler {
private SingleThread()
{
//When this function is running, no other crawler should do anything
}
#Override
public void visit(Page page) {
if(SomeCriteria())
{
//make all other crawlers stop until I finish
SingleThread();
//let them resume
}
//Normal Stuff
}
}
Here is a short example on how to achieve this with the cool java concurrency stuff:
snip old code doesn't matter anymore with the Pause class.
EDIT:
Here is the new Test class:
package de.hotware.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
private Pause mPause;
public Test() {
this.mPause = new Pause();
}
public void concurrent() throws InterruptedException {
while(true) {
this.mPause.probe();
System.out.println("concurrent");
Thread.sleep(100);
}
}
public void crucial() throws InterruptedException {
int i = 0;
while (true) {
if (i++ % 2 == 0) {
this.mPause.pause(true);
System.out.println("crucial: exclusive execution");
this.mPause.pause(false);
} else {
System.out.println("crucial: normal execution");
Thread.sleep(1000);
}
}
}
public static void main(String[] args) {
final Test test = new Test();
Runnable run = new Runnable() {
#Override
public void run() {
try {
test.concurrent();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Runnable cruc = new Runnable() {
#Override
public void run() {
try {
test.crucial();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
ExecutorService serv = Executors.newCachedThreadPool();
serv.execute(run);
serv.execute(run);
serv.execute(cruc);
}
}
And the utility Pause class:
package de.hotware.test;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Utility class to pause and unpause threads
* with Java Concurrency
* #author Martin Braun
*/
public class Pause {
private Lock mLock;
private Condition mCondition;
private AtomicBoolean mAwait;
public Pause() {
this.mLock = new ReentrantLock();
this.mCondition = this.mLock.newCondition();
this.mAwait = new AtomicBoolean(false);
}
/**
* waits until the threads until this.mAwait is set to true
* #throws InterruptedException
*/
public void probe() throws InterruptedException {
while(this.mAwait.get()) {
this.mLock.lock();
try {
this.mCondition.await();
} finally {
this.mLock.unlock();
}
}
}
/**
* pauses or unpauses
*/
public void pause(boolean pValue) {
if(!pValue){
this.mLock.lock();
try {
this.mCondition.signalAll();
} finally {
this.mLock.unlock();
}
}
this.mAwait.set(pValue);
}
}
The basic usage is to call probe() before each run. This will block if it is paused until pause(false) is called.
Your class would look like this:
public class TestCrawler extends WebCrawler {
private Pause mPause;
public TestCrawler(Pause pPause) {
this.mPause = pPause;
}
private SingleThread()
{
//When this function is running, no other crawler should do anything
}
#Override
public void visit(Page page) {
if(SomeCriteria())
{
//only enter the crucial part once if it has to be exclusive
this.mPause.probe();
//make all other crawlers stop until I finish
this.mPause.pause(true);
SingleThread();
//let them resume
this.mPause.pause(false);
}
this.mPause.probe();
//Normal Stuff
}
}
public class StockMonitor extends Thread {
private boolean suspend = false;
private volatile Thread thread;
public StockMonitor() {
thread = this;
}
// Use name with underscore, in order to avoid naming crashing with
// Thread's.
private synchronized void _wait() throws InterruptedException {
while (suspend) {
wait();
}
}
// Use name with underscore, in order to avoid naming crashing with
// Thread's.
public synchronized void _resume() {
suspend = false;
notify();
}
// Use name with underscore, in order to avoid naming crashing with
// Thread's.
public synchronized void _suspend() {
suspend = true;
}
public void _stop() {
thread = null;
// Wake up from sleep.
interrupt();
}
#Override
public void run() {
final Thread thisThread = Thread.currentThread();
while (thisThread == thread) {
_wait();
// Do whatever you want right here.
}
}
}
Calling _resume and _suspend will enable you to resume and pause the Thread. _stop will let you stop the thread gracefully. Note that, once you stop the Thread, there is no way to resume it again. The Thread is no longer usable.
The code is being picked from a real world open source project : http://jstock.hg.sourceforge.net/hgweb/jstock/jstock/file/b17c0fbfe37c/src/org/yccheok/jstock/engine/RealTimeStockMonitor.java#l247
You can use wait() and notify()
thread waiting:
// define mutex as field
Object mutex = new Object();
// later:
synchronized(mutex) {
wait();
}
notify the thread to continue
synchronized (mutex) {
notify();
}