多线程回调方法

3
我在我的应用程序中有一个名为Service的服务,它允许客户端注册以从服务接收回调。我尝试实现这样一个机制,使得当客户端回调实现被调用时,它们可以在服务线程上异步地运行或按顺序运行。具体的回调行为取决于使用哪种方法为客户端注册回调。客户可以使用registerClientForCallbacks来注册以便在主线程上进行回调,或者使用registerClientForAsyncCallbacks来注册以便在新线程上进行回调。
问题在于,当我尝试在新线程上调用回调时,线程会阻塞在thread.run()上,直到可运行任务完成,从而有效地消除了我的多线程尝试。我在下面发布了我的服务代码(包含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();
    }
}

你为什么在线程上调用 run() 而不是 start() - WalterM
1个回答

3
你必须使用t.start()而不是t.run()t.run()直接调用你的可运行对象的run()方法。t.start()启动一个新线程,然后调用run()方法。
此外,你应该考虑使用Executor而不是直接创建和启动线程...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接