android多线程:thread.join()无法按预期工作



我在下面的代码中使用thread.join时遇到问题。它应该等待线程完成后再执行后面的代码,对吧?它在不同的场合表现不同。

我有三个案例要检查我的代码是否正常

  • 应用程序是第一次使用-工作正常,但下载时没有出现加载页面
  • 应用程序第二次使用(数据库是最新的)-工作正常
  • 应用程序第三次使用(数据库已过时,必须更新)-不会更新,屏幕熄灭,然后崩溃

我想我对onCreate方法上的这个代码有问题:

dropOldSchedule();
dropThread.join();
triggerDownload();

根据日志,代码一直工作到本部分之前。。。问题出在哪里?


MainActivity.java

public class MainActivity extends Activity {
final static int INDEX_ACCTTYPE = 0; 
final static int INDEX_ECN = 1; 
final static int INDEX_TLN = 2; 
final static int INDEX_SIN = 3; 
final static int INDEX_MOBILE = 4; 
final static int INDEX_CITY = 5;
final static int INDEX_START_DATE = 6;
final static int INDEX_START_TIME = 7;
final static int INDEX_END_DATE = 8; 
final static int INDEX_END_TIME = 9; 
final static int INDEX_REASON = 10;
final static int INDEX_DETAILS = 11;
DatabaseHandler db;
String str;
ProgressDialog pd;
TextView homeText1, homeText2, homeText3, homeText4;
final private String csvFile = "http://www.meralco.com.ph/pdf/pms/pms_test.csv";
final private String uploadDateFile = "http://www.meralco.com.ph/pdf/pms/UploadDate_test.txt";
Thread dropThread = new Thread(new Runnable() {
    public void run() {
        db = new DatabaseHandler(MainActivity.this);
        db.dropOldSchedule(); 
        runOnUiThread(new Runnable() {
            public void run() {
                while (!pd.isShowing());
                db.close();
                pd.dismiss();
            }
        });
    }
});
Thread getUploadDateThread = new Thread(new Runnable() {
    public void run() {
        try {
            URL myURL = new URL(uploadDateFile);
            BufferedReader so = new BufferedReader(new InputStreamReader(myURL.openStream()));
            while (true) {
                String output = so.readLine();
                if (output != null) {
                    str = output;
                }
                else {
                    break;
                }
            }
        so.close();
        }
        catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 
        runOnUiThread(new Runnable() {
            public void run() {
                while (!pd.isShowing());
                pd.dismiss();
            }
        });
    }
    });
Thread downloadThread = new Thread(new Runnable() {
    public void run() {
        db = new DatabaseHandler(MainActivity.this);
        db.beginTransaction();
        try {
            URL url = new URL(csvFile);
            Log.i("dl", "start");
            InputStream input = url.openStream();
            CSVReader reader = new CSVReader(new InputStreamReader(input));
            Log.i("dl", "after reading");
            String [] sched;
            while ((sched = reader.readNext()) != null) {
                if(sched[INDEX_CITY].equals("")) sched[INDEX_CITY]="OTHERS";
                try {
                    db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
                            sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
                            sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
                            sched[INDEX_DETAILS], sched[INDEX_REASON]);
                } catch (IndexOutOfBoundsException e) {
                    db.addRow(sched[INDEX_SIN], sched[INDEX_CITY], 
                            sched[INDEX_START_DATE], sched[INDEX_START_TIME], 
                            sched[INDEX_END_DATE], sched[INDEX_END_TIME], 
                            "", sched[INDEX_REASON]);
                    //e.printStackTrace();
                }
            }
            input.close();
            Log.i("dl", "finished");
        } catch (MalformedURLException e) {
            e.printStackTrace();
            db.endTransaction();
        } catch (IOException e) {
            e.printStackTrace();
            db.endTransaction();
        } 
        Log.d("Count", ""+db.count());
        db.setTransactionSuccessful();
        db.endTransaction();
        writeUploadDateInTextFile();
    }
});
@SuppressWarnings("unqualified-field-access")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.pms_main);
    Button home = (Button) findViewById(R.id.home);
    home.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, MeralcoSuite_TabletActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            finish();
        }
    });
    homeText1 = (TextView) findViewById(R.id.home_text1);
    homeText2 = (TextView) findViewById(R.id.home_text2);
    homeText3 = (TextView) findViewById(R.id.home_text3);
    homeText4 = (TextView) findViewById(R.id.home_text4);
    homeText1.setVisibility(View.INVISIBLE);
    homeText2.setVisibility(View.INVISIBLE);
    homeText3.setVisibility(View.INVISIBLE);
    homeText4.setVisibility(View.INVISIBLE);
    getUploadDate();
    try {
        getUploadDateThread.join();     //wait for upload date
        Log.d("getUploadDate","thread died, upload date=" + str);
        if(dbExists()){
            db = new DatabaseHandler(MainActivity.this);
            Log.d("Count", "" + db.count());
            db.close();
            if(!uploadDateEqualsDateInFile()){
                dropOldSchedule();
                    dropThread.join();
                triggerDownload();
            }
            showDisclaimer();
            Log.i("oncreate", "finished!");
            return;
        }
        triggerDownload();
        showDisclaimer();
        Log.i("oncreate", "finished!");
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public void dropOldSchedule(){
    if(pd!=null && pd.isShowing())
        pd.setTitle("Getting upload date...");
    else
        pd = ProgressDialog.show(this, "Getting upload date", 
            "This may take a few minutes...", true, false);

    dropThread.start();
}
public void triggerDownload() {
    if (!checkInternet()) {
        showAlert("An internet connection is required to perform an update, please check that you are connected to the internet");
        return;
    }
    if(pd!=null && pd.isShowing())
        pd.setTitle("Getting upload date...");
    else
        pd = ProgressDialog.show(this, "Getting upload date", 
            "This may take a few minutes...", true, false);
    downloadThread.start();
}
public void getUploadDate() {
    Log.d("getUploadDate", "getting upload date of schedule");
    if(pd!=null && pd.isShowing())
        pd.setTitle("Getting upload date...");
    else
        pd = ProgressDialog.show(this, "Getting upload date", 
            "This may take a few minutes...", true, false);

    getUploadDateThread.start();
}
public void writeUploadDateInTextFile() {
    Log.d("writeUploadDateTextFile", "writing:"+str);
    try {
        OutputStreamWriter out = new OutputStreamWriter(openFileOutput(
                "update.txt", 0));
        out.write(str);
        out.close();
    } catch (java.io.IOException e) {
        e.printStackTrace();
    }
}
public void showDisclaimer() {
    Log.d("ShowDisclaimer", "showing disclaimer");
    homeText3
    .setText("..." + str
            + "...");

    homeText1.setVisibility(View.VISIBLE);
    homeText2.setVisibility(View.VISIBLE);
    homeText3.setVisibility(View.VISIBLE);
    homeText4.setVisibility(View.VISIBLE);
    Log.d("showDisclaimer", "finished showing disclaimer");
}
public boolean uploadDateEqualsDateInFile() {
    Log.d("uploadDateEqualsDateInFile","comparing schedule upload dates");
    try {
            String recordedDate = "";
            InputStream instream = openFileInput("update.txt");
            if (instream != null) { // if file the available for reading
                Log.d("uploadDateEqualsDateInFile","update.txt found!");
                InputStreamReader inputreader = new InputStreamReader(instream);
                BufferedReader buffreader = new BufferedReader(inputreader);
                String line = null;
                while ((line = buffreader.readLine()) != null) {
                    recordedDate = line;
                    Log.d("uploadDateEqualsDateInFile","recorded:"+recordedDate);
                }
                Log.d("uploadDateEqualsDateInFile","last upload date: " + str + ", recorded:" +recordedDate);
                if(str.equals(recordedDate)) return true;
                return false;
            }
            Log.d("uploadDateEqualsDateInFile","update.txt is null!");
            return false;   
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        return false;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}
public boolean checkInternet() {
    ConnectivityManager cm = (ConnectivityManager) this
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo infos[] = cm.getAllNetworkInfo();
    for (NetworkInfo info : infos)
        if (info.getState() == NetworkInfo.State.CONNECTED
                || info.getState() == NetworkInfo.State.CONNECTING) {
            return true;
        }
    return false;
}
public boolean dbExists() {
    File database=getApplicationContext().getDatabasePath(DatabaseHandler.DATABASE_NAME);
    if (!database.exists()) {
        Log.i("Database", "Not Found");
        return false;
    }
    Log.i("Database", "Found");
    return true;
}
@Override
protected void onDestroy() {
    super.onDestroy();
    if (db != null) {
        db.close();
    }
}
@Override
protected void onPause() {
    super.onPause();
    if (db != null) {
        db.close();
    }
}

}

很抱歉,我在您的代码中找不到错误或问题。但我强烈建议您使用AsyncTask在不同的线程中执行某些操作。AsyncTask非常易于使用,我想说它是java最大的优势之一。我真的很怀念它。

http://labs.makemachine.net/2010/05/android-asynctask-example/

http://marakana.com/s/video_tutorial_android_application_development_asynctask_preferences_and_options_menu,257/index.html

查看这些链接,希望对你有所帮助。

已经提到AsyncTask是更好的选择。然而,可能的情况是,您对加入的调用将抛出InterruptedException。试着这样使用:

while(getUploadDateThread.isRunning()){
    try{
        getUploadDateThread.join();
    } catch (InterruptedException ie){}
}
// code after join

我认为您面临的问题是,当您在onCreate()方法中调用join时,会阻塞UI线程。您应该将此代码移动到另一个线程中,该线程应该在后台执行,一旦完成,您就可以更新UI。

这是一个示例代码:

    final Thread t1 = new Thread();
    final Thread t2 = new Thread();
    t1.start();
    t2.start();
    new Thread(new Runnable() {
        @Override
        public void run() {
            // Perform all your thread joins here.
            try {
                t1.join();
                t2.join();
            } catch (Exception e) {
                // TODO: handle exception
            }

            // This thread wont move forward unless all your threads
            // mentioned above are executed or timed out.
            // ------ Update UI using this method
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // Update UI code goes here
                }
            });
        }
    }).start();

最新更新