2015-05-31 27 views
1

我想在服務中創建一個具有3個線程的固定池的執行程序。線程在服務中啓動線程創建

這3個線程將根據我的SQLite數據庫做一些工作。

有沒有辦法告訴線程「呼」的服務,它會告訴他一些方法,「一個線程完成,你現在可以拉從數據庫中的數據,並啓動一個新線程」

這樣我可以操縱數據庫,接下來的線程將會相應地執行。

所有我能夠做到的是,填補了隊列所有我有我的數據庫中的數據,這樣,它不會反應在DB的變化,因爲我已經退出所有的數據

編輯:一些

public class MyThread implements Runnable { 

private File _file; 
private Context context; 
private DBHelper helper; 
private int requestId; 

public MyThread(File file, Context context, int requestId) { 
    this._file = file; 
    this.context = context; 
    this.requestId = requestId; 
} 

@Override 
public void run() { 
     // Thread work here 

     helper.deleteRequest(requestId);// remove from db to prevent infinite loop 

     // THIS IS THE QUESTION 
     MediaDownloadService.startNewThread();// ??? can it be done 

    } catch (IOException e) { 
     Log.e("Callable try", post.toString()); 

    } 
} 
當然,我不希望它是靜態的

,是否有任何其他的方式來做到這一點:爲更好地理解

public class MediaDownloadService extends Service { 
    public int onStartCommand(Intent intent, int flags, int startId) { 
    executor = new ThreadPoolExecutor(2,3,3000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); 
    //initiale start of new threads (first run) 
} 

public void startNewThread(){ 
    if(helper.requestsExists()){ 
     Map<Integer,String> requestMap = helper.getRequestsToExcute(0); 
     Set<Integer> keySet = requestMap.keySet(); 
     Iterator<Integer> iterator = keySet.iterator(); 
     executor.submit(new MyThread(file, getApplicationContext(), iteratorNext), 1); 
    }else{ 
     executor.shutdown(); 
     this.stopSelf(); 
    } 
} 

和線程自己的代碼?

+0

編輯以更好地瞭解一些代碼的問題,我想過將來objec像你提到的,但它的邏輯一直讓我失望,生病需要做一段時間(的Future.get()),並等待,直到它返回答案? –

回答

0

經過一番研究,我設法找到一個解決方案:

首先,我學會了如何通過這裏綁定的IBinder服務: https://www.youtube.com/watch?v=0c4jRCm353c

所以我服務,現在看起來就像這樣:

public class MediaDownloadService extends Service { 

private DBHelper helper; 
private ExecutorService executor; 
private final IBinder sharonsBinder = new MyLocalBinder(); 
File file; 

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


@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    helper = new DBHelper(getApplicationContext()); 
    executor = new ThreadPoolExecutor(2,3,3000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); 
    Log.e("requestsExists", helper.requestsExists() + ""); 
    if(helper.requestsExists()){ 
     // map of the index of the request and the string of the absolute path of the request 
     Map<Integer,String> requestMap = helper.getRequestsToExcute(3); 
     Set<Integer> keySet = requestMap.keySet(); 
     Iterator<Integer> iterator = keySet.iterator(); 
     Log.e("MAP",requestMap.toString()); 
     //checks if the DB requests exists 
     if(!requestMap.isEmpty()){ 
      //execute them and delete the DB entry 
      while(iterator.hasNext()){ 
       int iteratorNext = iterator.next(); 
       Log.e("ITREATOR", iteratorNext + ""); 
       file = new File(requestMap.get(iteratorNext)); 
       Log.e("file", file.toString()); 
       Log.e("thread Opened", "Thread"+iteratorNext); 
       executor.submit(new MyTask(file, getApplicationContext(), iteratorNext), 1); 
       helper.requestTaken(iteratorNext); 
      } 
     } 
    } 
    return START_STICKY; 
} 

public void startNewTask(){ 
    if(helper.requestsExists()){ 
     Map<Integer,String> requestMap = helper.getRequestsToExcute(1); 
     Set<Integer> keySet = requestMap.keySet(); 
     Iterator<Integer> iterator = keySet.iterator(); 
     while(iterator.hasNext()){ 
       int iteratorNext = iterator.next(); 
       file = new File(requestMap.get(iteratorNext)); 
       Log.e("file", file.toString()); 
       Log.e("thread Opened", "Thread"+iteratorNext); 
       executor.submit(new MyTask(file, getApplicationContext(), iteratorNext), 1); 
       helper.requestTaken(iteratorNext); 
      } 
    }else{ 
     executor.shutdown(); 
     this.stopSelf(); 
    } 
} 
public class MyLocalBinder extends Binder{ 
    MediaDownloadService getService(){ 
     return MediaDownloadService.this; 
    } 
} 

現在我將我的任務綁定到服務,以便能夠調用像這樣的startNewTask()方法:

public class MyTask implements Runnable { 

private File _file; 
private Context context; 
private DBHelper helper; 
private int requestId; 
private MediaDownloadService sharonsService; 
boolean isBound = false; 

public MyTask(File file, Context context, int requestId) { 
    this._file = file; 
    this.context = context; 
    this.requestId = requestId; 

} 

@Override 
public void run() { 
    Intent intent = new Intent(context,MediaDownloadService.class); 
    context.bindService(intent,sharonsConnection,Context.BIND_AUTO_CREATE); 

     // some work here 
     sharonsService.startNewTask(); 

    } catch (IOException e) { 
     Log.e("Callable try", post.toString()); 

    } 
} 

private ServiceConnection sharonsConnection = new ServiceConnection() { 
    @Override 
    public void onServiceConnected(ComponentName componentName, IBinder service) { 
     MyLocalBinder binder = (MyLocalBinder) service; 
     sharonsService = binder.getService(); 
     isBound = true; 
    } 

    @Override 
    public void onServiceDisconnected(ComponentName componentName) { 
     isBound = false; 
    } 
}; 

工作正常,只有當任務完成後

希望它會幫助人們與同一問題線程被打開。

0

我想你在這裏有一些誤解:Executor.submit()不接受Thread,而是Runnable。它會將Runnable放入一個隊列中,並可能(在一段時間後)分配一個線程來執行該runnable指定的動作。整個執行程序的存在使您不必自己執行線程創建,管理和任務調度。

因此ThreadPoolExecutor已實現您嘗試實施的排隊功能。因此,一個解決方案就是在執行者進來時簡單地提交所有任務。執行者將對它們進行排隊並將它們安排到可用線程。

另請注意,有AsyncTask.execureOnExecutor()也可以讓您在主線程上運行。

並請將MyThreadstartNewThread()重命名爲其他內容。前者不是線索,而只是一項任務,後者只向執行者提交工作。