首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ScheduledExecuterService.scheduleAtFixedRate创建多线程池- Android

ScheduledExecuterService.scheduleAtFixedRate创建多线程池- Android
EN

Stack Overflow用户
提问于 2013-04-05 13:36:28
回答 2查看 2.6K关注 0票数 4

我在我的安卓应用程序中有一个名为UploadManagerAsyncTask,它检查处理过的项目,并将它们上传到服务器。

为此,我使用ScheduledExecutorService.scheduleAtFixedRate每隔1分钟检查一次项目,并将它们上传到服务器。

然而,有时会创建多个线程池(这种情况发生的概率为10% ),由于有时相同的请求会被发送两次到服务器,尽管这种并发性是在服务器和客户机级处理的,但我仍然不希望这种情况发生在客户端。

下面是代码的样子。

在MainActivity (start-activity)中,我将UploadManager初始化为:

代码语言:javascript
复制
public class MainActivity extends BaseActivity {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       .
       .
       .
       new UploadManager().execute(this);
   }
}

UploadManager的工作原理如下:

代码语言:javascript
复制
public class UploadManager extends AsyncTask<Context, Integer, Integer> {

    private ScheduledExecutorService scheduledExecutorService;
    private static final int NUM_OF_THREADS = 5;
    private static final int DELAY_IN_SECONDS = 60;
    private Context context;
    private final Logger logger = new Logger(getClass().getSimpleName());

    protected Integer doInBackground(Context... context) {
        this.context = context[0];
        scheduledExecutorService = Executors.newScheduledThreadPool(NUM_OF_THREADS);
        scheduledExecutorService.scheduleAtFixedRate(postInformation, 5, DELAY_IN_SECONDS, TimeUnit.SECONDS);
       return 0;
    }

    private Runnable postInformation = new Runnable() {
        @Override
        public void run() {
            if (NetworkManager.isInternetAvailable(context)) {
                uploadAcknowledgement();
            }
        }
    };

    private void uploadAcknowledgement() {
        List<Acknowledgement> ackList = null;
        try {
            logger.info("RUNNING TASK TO POST ACKNOWLEDGEMENT");
            .
            .
        }
    }
}

当我检查日志时,它说:

代码语言:javascript
复制
35119 [pool-2-thread-1] INFO  Upload Manager - [1363841355530] : 21/03/2013 10:19:15 : RUNNING TASK TO POST ACKNOWLEDGEMENT  
35122 [pool-3-thread-1] INFO  Upload Manager - [1363841355532] : 21/03/2013 10:19:15 : RUNNING TASK TO POST ACKNOWLEDGEMENT

这清楚地表明现在有多个线程池,因此,uploadAcknowledgement()方法被多次调用。

在AndroidManifest.xml中,MainActivity声明为:

代码语言:javascript
复制
<application android:label="@string/app_name" android:icon="@drawable/icon">
    <activity android:name="MainActivity"
              android:label="@string/app_name"
              android:theme="@android:style/Theme.NoTitleBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
    </activity>
    .
    .
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-17 01:19:19

我最终找出了原因,如果ScheduledExecutor的服务重叠运行,那么它会产生新的工作线程(例如,在本例中,postInformation()创建一个新的工作线程),并最终产生一个新的池。

但是,可以使用newSingleThreadScheduledExecutor而不是newScheduledThreadPool(int corePoolSize)'来避免多个工作进程。

因此,不是将“`scheduledExecutorService”初始化为:

代码语言:javascript
复制
scheduledExecutorService = Executors.newScheduledThreadPool(NUM_OF_THREADS);  

它应该被初始化为:

代码语言:javascript
复制
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();  

这样可以确保没有多个工作线程在运行。

票数 2
EN

Stack Overflow用户

发布于 2013-04-13 13:48:38

您有一个包含N个文件的列表,并启动了X个线程来上传它,而没有指定哪个线程选择哪个文件。解决此问题的一种方法是将要上载的文件添加到阻塞队列中,并让线程从队列中挑选要上载的文件。这样,任何文件都不会被选中两次。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15826661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档