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

时间:2012-07-31 12:12:32

标签: android multithreading

我在下面的代码中使用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();
    }
}

}

4 个答案:

答案 0 :(得分:2)

抱歉,我在代码中找不到错误或问题。但我强烈建议您使用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

检查那些链接希望对您有所帮助。

答案 1 :(得分:1)

已经提到AsyncTask是更好的选择。但是,可能会出现这种情况,即您的加入调用将抛出InterruptedException。尝试使用它:

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

答案 2 :(得分:0)

我认为当你在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();

答案 3 :(得分:-1)

thread.join的重点是确保在继续当前执行之前,你所加入的任何线程上的所有进程都已完成。

如果您即将关闭某个程序并希望在结束之前确保保存等,那么这是有道理的。使用线程。加入你的onCreate并不是真的有帮助。

很抱歉,我知道这并不能解决您的疑问,但请确保您知道为什么使用thread.join!