Strange Concurrency Issue in Java Swing -


i have jframe application's window (appframe in following code) contains lot of logic , takes 1 second or load. in meantime want show user nice loading frame (initframe). however, when run code, initframe appear text in jlabel on doesn't appear - doesn't appear @ in brief moment till app frame loaded.

if comment out appframe, , launch initframe, text loaded instantly, no waiting time @ all. why so? might concurrency issue?

public static void main(string[] args) {     swingutilities.invokelater(new runnable() { //as per best practice concurrency in swing - see http://docs.oracle.com/javase/tutorial/uiswing/concurrency/         @override         public void run() {             final jframe initframe = new initframe();             initframe.setvisible(true);             final appframe appframe = new appframe();             appframe.setvisible(true);             initframe.setvisible(false);             initframe.dispose();         }     });  } 

here's example of might going wrong in appframe.

you can run test threading:

java splashtest true 

or without

java splashtest 

when threading enabled, see splashframe , appframe updating every 250ms, more or less.

when threading not enabled, see splashframe no components showing, app 'hangs' 4 seconds, see appframe.

the example contrived, might give ideas.

note splashframe has no 'direct' connection appframe. communication through appframeworklistener interface.

i've put 'work' in appframe. if there lot of processing done should extracted out of ui code, run in separate thread, , appframe notified of progress task, in same way splashframe is.

import javax.swing.*;  class splashtest {      static boolean usethread = false;      public static void main(string[] args) {         // pass true @ command line turn on threading.         // no args, or value other true turn off threading.         if (args.length > 0) {             usethread = new boolean(args[0]);         }         swingutilities.invokelater(new runnable() {             @override             public void run() {                 splashframe splashframe = new splashframe();                 splashframe.setvisible(true);                 new appframe(splashframe).setvisible(true);             }});     }      private static class baseframe extends jframe {         public baseframe() {             setdefaultcloseoperation(jframe.dispose_on_close);             setsize(200, 200);             settitle(getclass().getsimplename());         }     }      private static class splashframe extends baseframe implements appframeworklistener {         jlabel status;          public splashframe() {             setlocation(0, 0);             status = new jlabel("splash frame");             getcontentpane().add(status);         }          public void appframeworkstart() {             status.settext("work started");         }          public void appframeworkprogress(long timeelapsed) {             status.settext("work has taken " + timeelapsed + "ms far");         }          public void appframeworkdone() {             // http://stackoverflow.com/questions/1234912/how-to-programmatically-close-a-jframe             setvisible(false);             dispose();         }     }      private static class appframe extends baseframe {         jlabel status;         appframeworklistener listener;          public appframe(appframeworklistener listener) {             setlocation(200, 200);             status = new jlabel("app frame");             getcontentpane().add(status);              this.listener = listener;              // none of 'heavy lifting' should in constructor.             if (usethread) {                 new thread(new runnable() {                     @override                     public void run() {                         dolotsofwork(4);                     }                 }).start();             } else {                 dolotsofwork(4);                 onworkdone();             }         }          private void dolotsofwork(int worklengthseconds) {             // we're starting. ensure onworkstart called on edt,             // method may called different thread.             invokeonworkstartonedt();              long start = system.currenttimemillis();              // hammer cpu "worklengthseconds" number of seconds.             // , contrived progress reporting.             long worklengthms = worklengthseconds * 1000;             while (system.currenttimemillis() - start < worklengthms) {                 long innerstart = system.currenttimemillis();                 // consume 250ms cpu before issuing progress update.                 while (system.currenttimemillis() - innerstart < 250);                 invokeonworkprogressonedt(system.currenttimemillis() - start);             }              // we're done now. ensure onworkdone called on edt,             // method may called different thread.             invokeonworkdoneonedt();         }          private void invokeonworkstartonedt() {             swingutilities.invokelater(new runnable() {                 @override                 public void run() {                     onworkstart();                 }             });         }          private void invokeonworkprogressonedt(final long timeelapsed) {             swingutilities.invokelater(new runnable() {                 @override                 public void run() {                     onworkprogress(timeelapsed);                 }             });         }          private void invokeonworkdoneonedt() {             swingutilities.invokelater(new runnable() {                 @override                 public void run() {                     onworkdone();                 }             });         }          private void onworkstart() {             status.settext("work started");             if (null != listener) {                 // tell who's interested in work status.                 listener.appframeworkstart();             }         }          private void onworkprogress(long timeelapsed) {             status.settext("work has taken " + timeelapsed + "ms far");             if (null != listener) {                 // tell who's interested in work status.                 listener.appframeworkprogress(timeelapsed);             }         }          private void onworkdone() {             status.settext("work done");             if (null != listener) {                 // tell who's interested in work status.                 listener.appframeworkdone();             }         }     }      interface appframeworklistener {         public void appframeworkdone();         public void appframeworkstart();         public void appframeworkprogress(long timeelapsed);     }  } 

Comments

Popular posts from this blog

linux - Does gcc have any options to add version info in ELF binary file? -

android - send complex objects as post php java -

charts - What graph/dashboard product is facebook using in Dashboard: PUE & WUE -