多线程回调方法

时间:2016-01-09 13:22:16

标签: java android multithreading

我的应用程序中有一个Service,它允许客户注册接收来自服务的回调。我试图实现它,以便在调用客户端回调实现时,它们可以异步运行,也可以在服务线程上按顺序运行。每个回调的具体行为取决于使用哪种方法注册客户端进行回调。客户端可以注册registerClientForCallbacks以使回调发生在主线程上,或者他们可以注册registerClientForAsyncCallbacks以使回调发生在新线程上。

我遇到的问题是,当我尝试在新线程上调用回调时,线程会阻塞thread.run()直到runnable完成,从而有效地消除了我对多线程的尝试。我已在下面发布了我的服务代码(使用Javadoc,因为我知道它很长)。有人可以帮我理解为什么callAllRegisteredClients中的线程不能同时运行?

public class ExampleService extends Service {
    /**
     * A record of the clients which have registered to receive callbacks from this service
     * asynchronously.
     */
    private Set<ClientCallbacks> registeredClientsAsync;

    /**
     * A record of the clients which have registered to receive callbacks from this service on the
     * service's main thread.
     */
    private Set<ClientCallbacks> registeredClientsMainThread;

    @Override
    public void onCreate() {
        super.onCreate();
        registeredClientsAsync = new HashSet<ClientCallbacks>();
        registeredClientsMainThread = new HashSet<ClientCallbacks>();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new LocalBinder();
    }

    /**
     * A binder with the singular purpose of returning a reference to the service.
     */
    public class LocalBinder extends Binder {
        public ExampleService getService() {
            return ExampleService.this;
        }
    }

    /**
     * Register this client to receive callback events from this service. Callback methods will
     * execute sequentially on the service's main thread. Consider using {@link
     * #registerClientForAsyncCallbacks(ClientCallbacks) registerClientForAsyncCallbacks} for
     * asynchronous callbacks.
     *
     * @param client the client to register, not null
     * @return true if the client is unregistered or has been
     * registered to receive callbacks asynchronously using {@link
     * #registerClientForAsyncCallbacks(ClientCallbacks) registerClientForAsyncCallbacks}, false
     * otherwise
     */
    public boolean registerClientForCallbacks(@NonNull ClientCallbacks client) {
        if (client == null) {
            throw new IllegalArgumentException("client cannot be null");
        }

        // Attempt to remove from async callbacks set (may do nothing)
        registeredClientsAsync.remove(client);

        return registeredClientsMainThread.add(client);
    }

    /**
     * Register this client to receive callback events from this service. Callback methods will be
     * executed asynchronously on separate threads.
     *
     * @param client the client to register, not null
     * @return true if the client is unregistered or has been
     * registered to receive callbacks in the service's main thread using {@link
     * #registerClientForCallbacks(ClientCallbacks) registerClientForCallbacks}, false
     * otherwise
     */
    public boolean registerClientForAsyncCallbacks(@NonNull ClientCallbacks client) {
        if (client == null) {
            throw new IllegalArgumentException("client cannot be null");
        }

        // Attempt to remove from async callbacks set (may do nothing)
        registeredClientsMainThread.remove(client);

        return registeredClientsAsync.add(client);
    }

    /**
     * Calls the {@link #ClientCallbacks ClientCallbacks} callback methods in all registered
     * clients. Clients registered for asynchronous callbacks will execute immediately, and
     * clients registered for sequential callbacks will be called in turn. Note that if the
     * callback methods block, then the service's main thread will block.
     */
    private void callAllRegisteredClients() {
        // First start asynchronous callbacks
        for (ClientCallbacks client : registeredClientsAsync) {
            Thread t = new Thread(new CallbackRunnable(client), client.toString());
            t.run();
        }

        // Finally start sequential callbacks
        for (ClientCallbacks client : registeredClientsMainThread) {
            client.onServiceEvent(this);
        }
    }

    /**
     * Interface allows callback events to be delivered to registered server clients.
     */
    public interface ClientCallbacks {
        public void onServiceEvent(Service service);
    }

    /**
     * A utility class which allows client callback methods to be executed asynchronously.
     */
    private class CallbackRunnable implements Runnable {
        /**
         * The client to receive the callbacks.
         */
        private final ClientCallbacks client;

        /**
         * Creates a new CallbackRunnable.
         * @param client the client to receive the callback methods, not null
         */
        private CallbackRunnable(@NonNull ClientCallbacks client) {
            if (client == null) {
                throw new IllegalArgumentException("client cannot be null");
            }

            this.client = client;
        }

        @Override
        public void run() {
            android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
            client.onServiceEvent(ExampleService.this);
        }
    }

    /*
     * Testing
     * TODO remove
     */
    public void activateCallbacks() {
        callAllRegisteredClients();
    }
}

1 个答案:

答案 0 :(得分:3)

您必须使用t.start()代替t.run()

t.run()直接调用runnable的run()方法。 t.start()启动一个新线程,然后调用run()方法。

此外,您应该考虑使用Executor而不是直接创建和启动线程......