java - Pause thread from another thread(s) and also stop/start it yet from another thread -


i've found good hints here. have more difficult task - additional requests are:
- low priority forever thread can started/stopped main thread (that's same) - has lock 1 resource exclusive access.
- low priority forever thread can paused/continued high priority thread(s) (they lock , use 1 resource)
- want low priority thread not release lock in each loop, release lock once told (for speed purposes - cos need init/deinit resource) (if have release lock every loop may let java manage competing threads , expect high priority threads win every , then).

i come solution , think safe , sound. i'm newbie i'm open finding bug in solution or suggestions improvements. questions are:
1) solution thread safe in cases?
2) optimal solution or can improve something?

if agreed let used template.

here core code:

flagnotify lowpriorrunreq   = new flagnotify(false); // low priority task run request flagnotify lowpriorpausereq = new flagnotify(false); // low priority task pause request (it uses notify) volatile boolean lowpriorrunflag = false;  // low priority task run flag lock      grouplock        = new reentrantlock();  // group lock (used acquire lowpriorrunflag correctly) semaphore resourcesemaphore = new semaphore(1);    // main semaphore protecting resource has accessed sequentially  public class prioritysingletaskthread extends thread {     @override     public void run() {         prn("high priority task created");         grouplock.lock();         if(lowpriorrunflag == true) lowpriorpausereq.setnotify(true);         resourcesemaphore.acquireuninterruptibly();         grouplock.unlock();         accessresource("high priority task");         resourcesemaphore.release();         grouplock.lock();         if(lowpriorpausereq.get() == true) lowpriorpausereq.setnotify(false);         grouplock.unlock();         prn("high priority task closed");     } }  public class lowprioritycontinuousthread extends thread {     void getresourcesemaphore(){         grouplock.lock();         resourcesemaphore.acquireuninterruptibly();         lowpriorrunflag = true;         grouplock.unlock();         accessresource("low priority init"); // here initialization , want happen on request priority thread     }     void releaseresourcesemaphore(){         accessresource("low priority de-init"); // here de-initialization , want happen on request priority thread         lowpriorrunflag = false;         resourcesemaphore.release();     }      @override     public void run() {         while(true){             //prn("low priority run req: "+lowpriorrunreq.get());             if(lowpriorrunreq.get() == true && lowpriorrunflag == false){                 prn("low  priority task starting");                 getresourcesemaphore();                 prn("low  priority task started");             }             if(lowpriorrunreq.get() == false && lowpriorrunflag == true){                 prn("low  priority task stopping");                 releaseresourcesemaphore();                 prn("low  priority task stopped");                 lowpriorrunreq.smartwait(true);             }             // note keep checking lowpriorrunflag. imagine there runflag detected high priority thread             // before de-asserted, pausereq requested high priority thread             // resource released when low priority task stops.             // high priority lock , use resource, since pausereq set             // thread try access device in order de-init , pause (unless check runflag)             if(lowpriorpausereq.get() == true && lowpriorrunflag == true){                 prn("low  priority task pausing");                 releaseresourcesemaphore();                 prn("low  priority task paused");                 lowpriorpausereq.smartwait(false);                 getresourcesemaphore();                 prn("low  priority task continue");             }             if(lowpriorrunflag){                 accessresource("low priority task");             }         }     } } 

and here full compilable java code including test bench (so have hint safe solution - never know threads)

import java.util.concurrent.semaphore; import java.util.concurrent.atomic.atomicinteger; import java.util.concurrent.locks.lock; import java.util.concurrent.locks.reentrantlock;  public class main {     // inner class setting flag , waiting notify - not hog cpu     public class flagnotify{         private boolean flag; // not synchro on boolean - immutable, new object created every value change....         private object synchro = new object();          public flagnotify(boolean val) {             flag = val;         }          public void setnotify(boolean val) {             synchronized (synchro) {                 flag = val;                 synchro.notify();             }         }          public boolean get(){             return flag;         }         public void smartwait(boolean expval){             synchronized (synchro){                 while(flag != expval){                     try {                         synchro.wait();                     } catch (interruptedexception e) {                         e.printstacktrace();                     }                 }             }         }     }      flagnotify lowpriorrunreq   = new flagnotify(false); // low priority task run request     flagnotify lowpriorpausereq = new flagnotify(false); // low priority task pause request (it uses notify)     volatile boolean lowpriorrunflag = false;  // low priority task run flag     lock      grouplock        = new reentrantlock();  // group lock (used acquire lowpriorrunflag correctly)     semaphore resourcesemaphore = new semaphore(1);    // main semaphore protecting resource has accessed sequentially      public class prioritysingletaskthread extends thread {         @override         public void run() {             prn("high priority task created");             grouplock.lock();             if(lowpriorrunflag == true) lowpriorpausereq.setnotify(true);             resourcesemaphore.acquireuninterruptibly();             grouplock.unlock();             accessresource("high priority task");             resourcesemaphore.release();             grouplock.lock();             if(lowpriorpausereq.get() == true) lowpriorpausereq.setnotify(false);             grouplock.unlock();             prn("high priority task closed");         }     }      public class lowprioritycontinuousthread extends thread {         void getresourcesemaphore(){             grouplock.lock();             resourcesemaphore.acquireuninterruptibly();             lowpriorrunflag = true;             grouplock.unlock();             accessresource("low priority init"); // here initialization , want happen on request priority thread         }         void releaseresourcesemaphore(){             accessresource("low priority de-init"); // here de-initialization , want happen on request priority thread             lowpriorrunflag = false;             resourcesemaphore.release();         }          @override         public void run() {             while(true){                 //prn("low priority run req: "+lowpriorrunreq.get());                 if(lowpriorrunreq.get() == true && lowpriorrunflag == false){                     prn("low  priority task starting");                     getresourcesemaphore();                     prn("low  priority task started");                 }                 if(lowpriorrunreq.get() == false && lowpriorrunflag == true){                     prn("low  priority task stopping");                     releaseresourcesemaphore();                     prn("low  priority task stopped");                     lowpriorrunreq.smartwait(true);                 }                 // note keep checking lowpriorrunflag. imagine there runflag detected high priority thread                 // before de-asserted, pausereq requested high priority thread                 // resource released when low priority task stops.                 // high priority lock , use resource, since pausereq set                 // thread try access device in order de-init , pause (unless check runflag)                 if(lowpriorpausereq.get() == true && lowpriorrunflag == true){                     prn("low  priority task pausing");                     releaseresourcesemaphore();                     prn("low  priority task paused");                     lowpriorpausereq.smartwait(false);                     getresourcesemaphore();                     prn("low  priority task continue");                 }                 if(lowpriorrunflag){                     accessresource("low priority task");                 }             }         }     } //------------------------------------------------------------------------- //-- following functions meant testing     atomicinteger clashdetector = new atomicinteger(0); // testing purposes      public void accessresource(string from){         prn("resource used "+from);         if(clashdetector.addandget(1)>1){             system.out.println("clash detected - bad programmer :((((((");             system.exit(-1);         }         sleeprandom(5);         clashdetector.getandadd(-1);     }      public void sleeprandom(long maxmilisec){         mysleep((long)(math.random()*maxmilisec));     }      public void mysleep(long milisec){         try{             thread.sleep(milisec);         }catch (interruptedexception e) {             e.printstacktrace();         }     }      void prn(string s){         system.out.println(s);     }      public void test(){         new lowprioritycontinuousthread().start();         for(long i=0; i< (long)1e3; i++){             lowpriorrunreq.setnotify(true);             for(int j=0; j<math.random()*100;j++){                 sleeprandom(10);                 new prioritysingletaskthread().start();             }             //sleeprandom(20);             lowpriorrunreq.setnotify(false);              for(int j=0; j<math.random()*20;j++){                 sleeprandom(10);                 new prioritysingletaskthread().start();             }             //sleeprandom(20);         }         mysleep(200);         system.out.println("test ok :)))))))))))))))))))))");         mysleep(200);         system.exit(0);     }      public static void main(string[] args) throws exception {         new main().test();     }  } 

i don't know means "start/stop" "forever thread", 1 design pattern can use pausing thread called "turnstile". here's 1 works when there 1 controller thread allowed "lock" or "unlock" turnstile:

import java.util.concurrent.semaphore;  class turnstile {     private final semaphore semaphore = semaphore.new(1);      // called "controller" thread.     public void lock() {         semaphore.acquire();     }      // called "controller" thread.     public void unlock() {         semaphore.release();     }      // called worker threads.     public void passthrough() {         semaphore.lock();         semaphore.release();     } } 

initially, turnstile in "unlocked" state, , passthrough() method promptly returns when ever worker calls it. if master thread "locks" turnstile, worker calls passthrough() blocked until master "unlocks" again. then, of workers "pass through", one-by-one.


you modify example if want have more 1 "master", it's decide how resolve conflict when 1 master wants turnstile locked, , wants unlocked.


then again, instead of modifying turnstile, write new multimasterturnstile handles conflict resolution , uses turnstile block workers.


Comments

Popular posts from this blog

PHP DOM loadHTML() method unusual warning -

python - How to create jsonb index using GIN on SQLAlchemy? -

c# - TransactionScope not rolling back although no complete() is called -