如何使用 java.util.concurrent 包实现后台线程?

Posted

技术标签:

【中文标题】如何使用 java.util.concurrent 包实现后台线程?【英文标题】:How to implement a background thread using java.util.concurrent package? 【发布时间】:2021-02-19 18:56:50 【问题描述】:

这是我首先使用的代码,但在最新的 android 版本中,AsyncTask 类已被弃用,并且 因此它没有响应,然后我使用了Thread 类,但该类也无法正常工作。 我想要与AsyncTask 类相同的结果。 我知道我必须使用 java.util.concurrent 包的一些执行程序类,但不知道使用哪个以及如何使用它。 请帮我解决这个问题。

private static final String USGS_REQUEST_URL =
            "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2016-01-01&endtime=2016-05-02&minfelt=50&minmagnitude=5";

EarthquakeAsyncTask task = new EarthquakeAsyncTask();
        task.execute(USGS_REQUEST_URL);
private class EarthquakeAsyncTask extends AsyncTask<String, Void, Event> 

        @Override
        protected Event doInBackground(String... urls) 

            // Perform the HTTP request for earthquake data and process the response.
            Event result = Utils.fetchEarthquakeData(urls[0]);
            return result;
        

        @Override
        protected void onPostExecute(Event result) 
            // Update the information displayed to the user.
            updateUi(result);
        
    
private static final String USGS_REQUEST_URL =
            "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=2016-01-01&endtime=2016-05-02&minfelt=50&minmagnitude=5";

earthquakeRunnable runnable = new earthquakeRunnable(USGS_REQUEST_URL);
        runnable.start();

private class earthquakeRunnable extends Thread

            String urls;
            earthquakeRunnable(String url)
                this.urls = url;
            
            @Override
            public void run() 
                // Perform the HTTP request for earthquake data and process the response.
                Event result = Utils.fetchEarthquakeData(urls);
                // Update the information displayed to the user
                updateUi(result);
            
        

【问题讨论】:

【参考方案1】:

这是一个示例,说明如何在 Activity/Fragment 中使用 ExecutorService:

// Create some member variables for the ExecutorService 
// and for the Handler that will update the UI from the main thread
ExecutorService mExecutor = Executors.newSingleThreadExecutor();
Handler mHandler = new Handler(Looper.getMainLooper());

// Create an interface to respond with the result after processing
public interface OnProcessedListener 
    public void onProcessed(Event result);


private void processInBg(final String url, final boolean finished)
    
    final OnProcessedListener listener = new OnProcessedListener()
        @Override
        public void onProcessed(Event result)
            // Use the handler so we're not trying to update the UI from the bg thread
            mHandler.post(new Runnable()
                @Override
                public void run()
                    // Update the UI here
                    updateUi(result);
                    
                    // ...
                    
                    // If we're done with the ExecutorService, shut it down.
                    // (If you want to re-use the ExecutorService,
                    // make sure to shut it down whenever everything's completed
                    // and you don't need it any more.)
                    if(finished)
                        mExecutor.shutdown();
                    
                
            );
        
    ;
    
    Runnable backgroundRunnable = new Runnable()
        @Override
        public void run()
            // Perform your background operation(s) and set the result(s)
            Event result = Utils.fetchEarthquakeData(url);
            
            // ...
            
            // Use the interface to pass along the result
            listener.onProcessed(result);
        
    ;
    
    mExecutor.execute(backgroundRunnable);

然后,无论您需要在哪里触发后台处理:

processInBg("some_url", true);

根据您的情况,您需要自定义 ExecutorService 的实现以更好地满足您的需求。

【讨论】:

Handler 类显示它已被弃用,并且您声明的所有变量都给出了一个错误,即向所有变量声明 final 并且如果它被分配给 final 那么它不能被分配一个新值. 感谢您的帮助,只是需要一些声明更改并且方法是正确的。谢谢! 我想问点别的,handler类和handler类对象有什么用???? 我很抱歉。我是即时写的,忽略了最终的变量声明。是的, Handler() 构造函数已被弃用。构造函数应该是 Handler(Looper.getMainLooper())。我已经更新了我的答案以包含这些内容并展示如何使用界面进行响应。 我包含 Handler 的原因是因为 UI 必须从主线程更新。这是在后台线程上运行后返回主线程的方法之一。

以上是关于如何使用 java.util.concurrent 包实现后台线程?的主要内容,如果未能解决你的问题,请参考以下文章

Java 并发工具包 java.util.concurrent 大全

如何解决错误:java.util.concurrent.ExecutionException: java.lang.RuntimeException: No server to serve reque

初始化后如何更新java.util.concurrent.ConcurrentLinkedQueue#head?

如何修复错误:java.util.concurrent.ExecutionException:com.android.ide.common.process.ProcessException:

java.util.concurrent的并发 Collection

java.util.concurrent.CopyOnWriteArrayList