我对线程的使用有一些疑问,特别是当你必须等待线程完成以便你可以执行其他操作时。
在我的应用程序中,我使用线程进行http连接等操作,或者在读取或写入RecordStore时使用线程。
例如,在我用于初始化线程的以下类中,我使用名为 HttpQueryCustomers 的方法从Web服务中检索一些客户。
public class thrLoadCustomers implements Runnable {
private RMSCustomer mRMSCustomer;
private String mUrl;
public thrLoadCustomers(RMSCustomer rmsCust, String url) {
mRMSCustomer = rmsCust;
mUrl = url;
}
public void run() {
String jsonResultados = "";
try {
jsonResultados = HttpQueryCustomers();
} catch (IOException ex) {
//How to show a message from here??
} catch (SecurityException se) {
//How to show a message here??
} catch (NullPointerException npe) {
//How to show a message from here??
}
if (!jsonResultados.equals("")) {
try {
mRMSCustomer.save(jsonResultados);
} catch (RecordStoreException ex) {
//How to show a message from here???
}
}
}
public String HttpQueryCustomers() throws IOException,SecurityException,NullPointerException {
StringBuffer stringBuffer = new StringBuffer();
HttpConnection hc = null;
InputStream is = null;
System.out.println(mUrl);
try {
hc = (HttpConnection) Connector.open(mUrl);
if (hc.getResponseCode() == HttpConnection.HTTP_OK) {
is = hc.openInputStream();
int ch;
while ((ch = is.read()) != -1) {
stringBuffer.append((char) ch);
}
}
} finally {
is.close();
hc.close();
}
String jsonData = stringBuffer.toString();
return jsonData.toString();
}
}
请注意,在上面的课程中,我传递了一个名为 rmsCust 的参数 RMSCustomer
RMSCustomer 是一个用于处理与RMS相关的所有操作的类:
public class RMSCustomer {
private String mRecordStoreName;
private Customer[] mCustomerList;
public RMSCustomer(String recordStoreName) {
mRecordStoreName = recordStoreName;
}
public Customer[] getCustomers() {
return mCustomerList;
}
public Customer get(int index) {
return mCustomerList[index];
}
public void save(String data) throws RecordStoreException,JSONException,NullPointerException {
RecordStore rs = null;
int idNuevoRegistro;
String stringJSON;
try {
rs = RecordStore.openRecordStore(mRecordStoreName, true);
JSONArray js = new JSONArray(data);
//Set the size of the array
mCustomerList = new Customer[js.length()];
for (int i = 0; i < js.length(); i++) {
JSONObject jsObj = js.getJSONObject(i);
stringJSON = jsObj.toString();
idNuevoRegistro = addRecord(stringJSON, rs);
//Add a new Customer to the array
mCustomerList[i] = initializeCustomer(stringJSON, idNuevoRegistro);
}
} finally {
if (rs != null) {
rs.closeRecordStore();
}
}
}
public int addRecord(String stringJSON, RecordStore rs) throws JSONException,RecordStoreException {
byte[] raw = stringJSON.getBytes();
int idNuevoRegistro = rs.addRecord(raw, 0, raw.length);
return idNuevoRegistro;
}
public Customer initializeCustomer(String stringJSON, int idRecord) throws JSONException {
Customer c = new Customer();
JSONObject jsonObj = new JSONObject(stringJSON);
// Set Customer properties
//...
return c;
}
}
此类用于显示客户列表,如您所见,它扩展了列表类,并接收一组Customers作为参数。
public class ListCustomers extends List {
private final Customer[] mData;
public static ListCustomers create(Customer[] data) {
int i = 0;
for (; i < data.length; i++) {
if (data[i] == null) {
break;
}
}
String[] names = new String[i];
for (int j = 0; j < i; j++) {
names[j] = data[j].name;
}
return new ListCustomers(names, data);
}
protected ListCustomers(String names[], Customer[] data) {
super("List of Customer", IMPLICIT, names, null);
mData = data;
}
public Customer getSelectedObject() {
return mData[this.getSelectedIndex()];
}
}
当我想要显示一个客户列表时,这就是我从MIDlet调用线程(使用所有前3个类)的方式:
private void showCustomerList(String url) {
showWaitForm();
if (scrCustomerList == null) {
rmsCustomers = new RMSCustomer("rmsCustomers");
thrLoadCustomers load = new thrLoadCustomers(rmsCustomers, url);
Thread t = new Thread(load);
t.start();
try {
t.join();
} catch (InterruptedException ex) {
}
scrCustomerList = ListCustomers.create(rmsCustomers.getCustomers());
scrCustomerList.addCommand(cmdSelect);
scrCustomerList.addCommand(cmdBack);
scrCustomerList.setCommandListener(this);
}
mDisplay.setCurrent(scrCustomerList);
}
现在我遇到的问题是:
showWaitForm()
不起作用(它设置一个带有Gauge的表单作为
目前的表格)t.join()
是否是最佳选择特别是线程可能是稀缺商品。 MSA 规范要求必须允许应用程序创建 十个帖子。只是因为你不能意味着你应该这样做。一般来说, 尽量使用尽可能少的资源,以便您的应用程序能够使用 尽可能顺利地运行
这是第一次使用线程,而在我的应用程序中,我可能最多有10个线程(类)。但是,我当时只会执行一次线程,我是否会反对前一个引用所说的内容?
我希望我不会问太多问题。非常感谢你的帮助。
P.D在Gregor Ophey
的帮助下,我在这里发布的大部分代码都无法实现答案 0 :(得分:2)
问题#1是关于与线程无关的不同问题,并且显示的代码非常少。我建议你发布一个新的专门问题,并对问题进行适当的解释。
问题#2和#3:你可以定义一个这样的包装类:
public class WSResult {
private boolean success; //true if the WS call went ok, false otherwise
private String errorMessage; //Error message to display if the WS call failed.
private Object result; //Result, only if the WS call succeeded.
private boolean completed = false;
//TODO getter and setters methods here
}
在屏幕中,您可以创建结果实例并等待它:
WSResult result = new WSResult();
//Start thread here
new Thread(new LoadCustomersTask(result)).start();
//This is old school thread sync.
synchronized(result){
while(!result.isCompleted()){
result.wait();
}
}
//Here the thread has returned, and we can diaplay the error message if any
if(result.isSuccess()){
} else {
//Display result.getErrorMessage()
}
然后你的runnable会是这样的:
class LoadCustomersTask implements Runnable {
private final WSResult result;
public LoadCustomersTask(WSResult res){
result = res;
}
public void run(){
//Do the WS call
//If it went well
result.setSuccess(true);
result.setResult(jsonResultados);
//Else
result.setSuccess(false);
result.setErrorMessage("Your error message");
//In any case, mark as completed
result.setcompleted(true);
//And notify awaiting threads
synchronized(result){
result.notifyAll();
}
}
}
您也可以使用thread.join执行此操作,但是wait / notify更好,因为您不会使屏幕依赖于运行runnable的特定线程。您可以在结果实例上等待/通知,如图所示,或者如果只是一次性使用,可以在runnable上等待。
问题#4:是的线程不得滥用,特别是在JavaME中,程序通常在单核CPU中运行,频率为MHz。尽量不要同时运行超过1-3个线程。如果您确实需要,请考虑使用单个线程来运行所有后台任务(阻塞队列)。