线程同步无法正常工作

时间:2016-09-21 21:55:14

标签: java android multithreading

我有一个班负责处理与Google地图相关的所有事情

下面的代码是这个类的一个片段;在这个片段(processPaths方法)中我做了一个foreach来读取整个Marker列表,其中每次迭代我创建一个Path对象和两个实现Runnable的对象。其中一个对象是PathProducer,负责挂载JSON请求,获取响应,解码并返回LatLng列表;另一个将获取PathProducer创建的latLng列表,并将通知MapsActivity根据此列表添加折线。 Path对象由两个Runnable对象共享(这就是我锁定/同步此对象的原因,PathConsumer无法通知MapsActivity在PathProducer计算它之前绘制Path)。

public void processPaths(){   

        int count = 1;
        for (Marker m : markerList) {
            Path path = new Path(from, m.getPosition());
            PathProducer producer = new PathProducer("Producer " + count, path);
            PathConsumer consumer = new PathConsumer("Consumer " + count, path);

            producer.run();
            consumer.run();

            count++;
        }

    }

以下是我的Path,PathProducer和PathConsumer类

路径:

package com.trackit.app.utilities;

import android.util.Log;
import com.google.android.gms.maps.model.LatLng;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Shanx on 19/09/2016.
 */
public class Path{

private static final String TAG = Path.class.getSimpleName();

private LatLng from;
private LatLng to;
private List<LatLng> waypoint = new ArrayList<LatLng>();
private boolean created = false;

public Path(LatLng from, LatLng to){

    this.from = from;
    this.to = to;

    Log.e(TAG, "Path going from " + from + " to " + to + " created.");

}    

public LatLng getFrom(){

    return from;

}

public LatLng getTo(){

    return to;

}

public boolean wasCreated(){

    return created;

}

public List<LatLng> getWaypoint(){

    return waypoint;

}

public void setWaypoint(List<LatLng> path){

    waypoint = path;

}

public void created(boolean path){

    created = path;

}

}

PathProducer:

package com.trackit.app.utilities;

import android.app.ProgressDialog;
import android.widget.Toast;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.SphericalUtil;
import com.trackit.app.track_it_v002.MapsActivity;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * Created by Shanx on 16/09/2016.
 */
public class PathProducer implements Runnable {

    private String name;
    private String trackingMode = "walking";
    private Path path;

    public PathProducer(String name, Path path){

        this.name = name;
        this.path = path;

    }

    @Override
    public void run() {

        findPath();

    }

    private String createRequestURL(LatLng from, LatLng to){

        return "https://maps.googleapis.com/maps/api/directions/json?origin=" + Double.toString
            (from.latitude) + "," + Double.toString( from.longitude) +     "&destination=" +
            Double.toString(to.latitude) + "," + Double.toString(to.longitude) +
            "&sensor=false&mode=" + trackingMode + "&alternatives=true&" +
            "key=< my personal key =) >";

    }

    public void findPath(){

        //Getting the URL
        String url = createRequestURL(path.getFrom(), path.getTo());

        //Showing a dialog till we get the route
        final ProgressDialog loading =     ProgressDialog.show(MapsActivity.mActivity, "Getting Route",
            "Please wait...", false, false);

        //Creating a string request
        StringRequest stringRequest = new StringRequest(url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    loading.dismiss();

                    //Calling the method drawPath to draw the path
                    drawPath(response);
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    loading.dismiss();
                }
            });

        //Adding the request to request queue
        RequestQueue requestQueue =     Volley.newRequestQueue(MapsActivity.mActivity);
        requestQueue.add(stringRequest);

    }

    //The parameter is the server response
    private void drawPath(String result) {

        //Calculating the distance in meters
        Double distance = SphericalUtil.computeDistanceBetween(path.getFrom(), path.getTo());

        //Displaying the distance
        Toast.makeText(MapsActivity.mActivity, String.valueOf(distance + " Meters"), Toast.
            LENGTH_LONG).show();

        try {
            //Parsing json
            final JSONObject json = new JSONObject(result);
            JSONArray routeArray = json.getJSONArray("routes");
            JSONObject routes = routeArray.getJSONObject(0);
            JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
            String encodedString = overviewPolylines.getString("points");
            path.setWaypoint(PolylineEncoder.decodeA(encodedString));
            path.created(true);
            this.notify();
        }
        catch (JSONException e) {

        }

    }

    public String getName(){

    return name;

}

}

PathConsumer:

package com.trackit.app.utilities;

import android.graphics.Color;
import com.google.android.gms.maps.model.PolylineOptions;
import com.trackit.app.track_it_v002.MapsActivity;

/**
 * Created by Shanx on 20/09/2016.
 */
public class PathConsumer implements Runnable {

    private String name;
    private Path path;

    public PathConsumer(String name, Path path){

        this.name = name;
        this.path = path;

    }

    @Override
    public void run() {

        synchronized (path) {
            while(!path.wasCreated()) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        MapsActivity.mActivity.getMap().addPolyline(new PolylineOptions()
            .addAll(path.getWaypoint())
            .width(10)
            .color(Color.GREEN)
            .geodesic(true)
            .clickable(true)
        );

    }

    public String getName(){

        return name;

    }

}

触发按钮OnClick后调用processPaths方法;这是在我在GoogleMap对象中添加一些标记后发生的。

问题是,在地图中添加一些标记并调用processPaths()后,应用程序会冻结。我不熟悉Java中的多线程,但是我做了一些研究,我在这里读了一些帖子,但没有人能帮助我......

你们可以指出我的错误是什么?当我的朋友都没有使用特定的编程语言= S

时,StackOverflow总是我最后的选择

0 个答案:

没有答案