我有一些关于线程使用的问题,特别是当你必须等待一个线程完成以便你可以执行其他操作时。
在我的应用程序中,我使用线程的操作,如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的参数,类型为RMSCustomerRMSCustomer是我用来处理与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;
}
}
该类用于显示客户列表,正如您所看到的,它扩展了 list 类并接收客户数组作为参数。
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()
不工作(它设置了一个表单与测量作为目前的形式) - 我不知道如何显示所有可能被抛出的异常在thrLoadCustomers类中
- 我不知道使用
t.join()
是否是最好的选择 - 最后一个问题是关于我正在读的一本书所说的:
特别是线程,可能是一种稀缺商品。MSA的规范要求必须允许应用程序创建<<strong> 10个线程/strong>。你能做并不意味着你应该做。一般来说,尽量使用最少的资源,这样您的应用程序就可以尽量平稳运行
这是第一次使用线程,在我的应用程序中,我可能有多达10个线程(类)。然而,我一次只执行一个线程,我是否违背了前面的报价??
我希望我没有问太多问题。非常感谢您的帮助。p。如果没有Gregor Ophey
问题#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
}
在您的屏幕中,您可以创建一个result实例并等待它:
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()
}
那么你的可运行文件应该是这样的:
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();
}
}
}
你也可以用线程来做。Join,但是wait/notify更好,因为您不会使屏幕依赖于运行可运行程序的特定线程。您可以在结果实例上等待/通知,如所示,或者在可运行实例上等待/通知,如果它只用于一次使用。
问题#4:是的,线程不能被滥用,特别是在java中,程序通常在单核cpu中运行,频率在MHz数量级。尽量不要同时运行超过1-3个线程。如果你真的需要,考虑使用一个线程来运行所有后台任务(阻塞队列)。