线程池的使用(三)
  mrMLeSzj1mp0 2023年11月02日 66 0


一.概述

今天我们继续研究线程池的使用,因为这块确实可能比较麻烦,不多研究几次是根本不能搞懂的,先看效果图

效果一

线程池的使用(三)_ide

效果二

线程池的使用(三)_ide_02

二.代码

效果一(纯ExecutorService、AsyncTask、Runnable关联实现相关文件如下)

public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
//任务编号
private static int order = 0;
/**
* 总共多少任务(根据CPU个数决定创建活动线程的个数,这样取的好处就是可以让手机承受得住)
*/
// private static final int count = Runtime.getRuntime().availableProcessors()*2;
private static final int count = 6;//任务总数
/**
* 每次只执行一个任务的线程池
*/
private static ExecutorService sSingleThreadExecutor;
/**
* 没有任务个数限制的线程池
*/
private static ExecutorService sCachedThreadPool;
/**
* 限制任务个数的线程池
*/
private static ExecutorService sFixedThreadPool;
/**
* 按指定时间可周期性执行任务的线程池
*/
private static ExecutorService sScheduledThreadPool;
/**
* 按指定时间可周期性执行任务的线程池,按照指定的工厂模式
*/
private static ExecutorService sScheduledThreadPool1;
private List<PoolTask> mPoolTasks;
private ListView mListView;
private boolean isCancel = false;
private boolean isClick = false;
/**
* 当前线程执行器类型
*/
private static ExecutorService currentExecutor ;
/**
* 方式一,使用默认线程工厂
*/
ThreadFactory ft = Executors.defaultThreadFactory();
/**
* 方式二,创建新线程需要的线程工厂
*/
private static ThreadFactory mThreadFactory = new ThreadFactory() {
private final AtomicInteger count = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "threadPool" + count.getAndIncrement());
thread.setDaemon(true);
return thread;
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.listview);
mListView.setOnItemClickListener(mOnItemClickListener);
initData();
}
public void initData(){
sSingleThreadExecutor = Executors.newSingleThreadExecutor();
sCachedThreadPool = Executors.newCachedThreadPool();
sFixedThreadPool = Executors.newFixedThreadPool(3);
sScheduledThreadPool = Executors.newScheduledThreadPool(3);
sScheduledThreadPool1 = Executors.newScheduledThreadPool(4, mThreadFactory);
sSingleThreadExecutor.submit(new Runnable() {
@Override
public void run() {
Log.i(TAG, "run: task is sumbit");
}
});
currentExecutor = sSingleThreadExecutor;
mListView.setAdapter(new ThreadPoolAdapter(this, count));
}

AdapterView.OnItemClickListener mOnItemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
//第一种关闭方式,等待正在执行的任务执行完成
// sCachedThreadPool.shutdown();
/*
shutdownNow:停止正在执行的任务,返回未执行的任务列表,第二次再调用shutDown
不会返回未执行的任务列表,当前执行器会变为空,因为线程池已经关闭了
*/
System.out.println("=========currentExecutor"+currentExecutor);
List<Runnable> runnables = currentExecutor.shutdownNow();
System.out.println("==========="+runnables);
for (Runnable r : runnables) {
System.out.println("=========未执行的任务信息"+r.toString());
}
System.out.println("=========isShoutDown"+currentExecutor.isShutdown());
currentExecutor = null;
}
//以第二项为例进行测试
PoolTask poolTask = mPoolTasks.get(1);
if (position == 1) {
if (!isClick) {
poolTask.cancel(true);
isCancel = true;
isClick = !isClick;
} else {
poolTask.cancel(false);
isCancel = false;
isClick = !isClick;
if (poolTask != null && poolTask.getStatus() == AsyncTask.Status.RUNNING) {
if (poolTask.isCancelled()) {
poolTask = new PoolTask(poolTask.itemview);
} else {
Toast.makeText(MainActivity.this, "任务已经在执行", Toast.LENGTH_SHORT).show();
}
}
if (currentExecutor == null) {
currentExecutor = Executors.newCachedThreadPool();
}
poolTask.executeOnExecutor(currentExecutor);//只能执行一次,也就是说第二个只能点击两次
}
} else {
Toast.makeText(MainActivity.this, "其他的", Toast.LENGTH_SHORT).show();
poolTask.cancel(false);
isCancel =false;
}
}
};

class PoolTask extends AsyncTask<Void, Integer, Void> {
private View itemview;
private final TextView mTextView;
private final ProgressBar mPb;
private String id;
public PoolTask(View itemview){
this.itemview = itemview;
mTextView = (TextView) itemview.findViewById(R.id.textview);
mPb = (ProgressBar) itemview.findViewById(R.id.pb);
if(order<count ||order == count){
id = "执行:" + String.valueOf(++order);
}else{
order = 0;
id = "执行:" + String.valueOf(++order);
}
}

@Override
protected void onPreExecute() {
super.onPreExecute();
mTextView.setText(id);
}

@Override
protected Void doInBackground(Void... params) {
if(!isCancelled()&&isCancel == false){ //这个地方很关键,如果不设置标志位的话,直接setCancel(true)是无效的
int prog = 0;
while (prog<101){
if ((prog > 0 || prog == 0) && prog < 70) // 小于70%时,加快进度条更新
{
SystemClock.sleep(100);
}
else
// 大于70%时,减慢进度条更新
{
SystemClock.sleep(300);
}
publishProgress(prog); // 更新进度条
prog++;
}
}
return null;
}

@Override
protected void onProgressUpdate(Integer... values) {//values是从publishProgress方法传过来的
super.onProgressUpdate(values);
mPb.setProgress(values[0]);
}
}
class ThreadPoolAdapter extends BaseAdapter{
private Context mContext;
private LayoutInflater mInflater;
private int taskcount;
public ThreadPoolAdapter(Context context,int taskCount){
mContext = context;
taskcount = taskCount;
mInflater = LayoutInflater.from(mContext);
mPoolTasks = new ArrayList<>();
}
@Override
public int getCount() {
return taskcount;
}

@Override
public Object getItem(int position) {
return mPoolTasks.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = mInflater.inflate(R.layout.list_view_item,null);
PoolTask poolTask = new PoolTask(convertView);
//根据指定的执行器执行任务
poolTask.executeOnExecutor(currentExecutor);
mPoolTasks.add(poolTask);
}
return convertView;
}
}
}

效果二(Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService关联实现)

public class MainActivity extends AppCompatActivity {
//线程池是否处于运行状态
private boolean isRunning = true;
//是否唤醒线程池工作
private boolean isNotify = true;
//在此类中使用同步锁时使用如下lock对象即可,官方推荐的,不推荐直接使用MainActivity.this类型的
private Object lock = new Object();
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mProgressBar.setProgress(msg.what);
}
};
//任务执行队列
private ConcurrentLinkedQueue<MyRunnable> taskQueue;
//正在等待执行或者已经完成的任务队列,线程安全的(HashMap是线程不安全的)
private ConcurrentHashMap<Future, MyRunnable> taskMap;
//创建一个不限制大小的线程池 此类主要有以下好处 1,以共享的无界队列方式来运行这些线程. 2,执行效率高。
// 3,在任意点,在大多数 nThreads 线程会处于处理任务的活动状态
//4,如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。
private ExecutorService mCachedThreadPool;
private ProgressBar mProgressBar;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
taskQueue = new ConcurrentLinkedQueue<MyRunnable>();
taskMap = new ConcurrentHashMap<Future, MyRunnable>();
if (mCachedThreadPool == null) {
mCachedThreadPool = Executors.newCachedThreadPool();
}
}

public void click(View view) {
switch (view.getId()) {
case R.id.add:
addTask(new MyRunnable(mHandler));
break;
case R.id.start:
startTask();
break;
case R.id.cancel:
cancelTask();
break;
case R.id.release:
releaseTask();
break;
case R.id.reload:
reloadTask(new MyRunnable(mHandler));
break;
}
}

public void addTask(final MyRunnable myRunnable){
mHandler.sendEmptyMessage(0);
if(mCachedThreadPool == null){
mCachedThreadPool = Executors.newCachedThreadPool();
notifyWork();
}
if(taskMap == null){
taskMap = new ConcurrentHashMap<>();
}
if(taskQueue == null){
taskQueue = new ConcurrentLinkedQueue<>();
}

mCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
taskQueue.offer(myRunnable);//插入一个Runnable到任务队列
notifyWork();
}
});
Toast.makeText(MainActivity.this, "已添加一个新任务到线程池中 !",Toast.LENGTH_SHORT).show();
}

public void startTask(){
if(mCachedThreadPool == null||taskMap == null||taskQueue == null){
return;
}
mCachedThreadPool.execute(new Runnable() {
private MyRunnable mMyRunnable;
@Override
public void run() {
if(isRunning){
synchronized (lock){
mMyRunnable = taskQueue.poll();//从线程队列里面取出一个Runnable用来执行
if(mMyRunnable == null){
isNotify = true;
}
}
if(mMyRunnable!=null){
taskMap.put(mCachedThreadPool.submit(mMyRunnable),mMyRunnable);
}
}
}
});
}

public void cancelTask(){
Toast.makeText(this, "任务被取消", Toast.LENGTH_SHORT).show();
for(MyRunnable mr:taskMap.values()){
mr.setCancelTask(true);
}
}

public void reloadTask(final MyRunnable myRunnable){
mHandler.sendEmptyMessage(0);
if(mCachedThreadPool == null){
mCachedThreadPool = Executors.newCachedThreadPool();
notifyWork();
}
if(taskMap == null){
taskMap = new ConcurrentHashMap<>();
}
if(taskQueue == null){
taskQueue = new ConcurrentLinkedQueue<>();
}
mCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
//插入一个Runnable对象到任务队列
taskQueue.offer(myRunnable);
notifyWork();
}
});
mCachedThreadPool.execute(new Runnable() {
@Override
public void run() {
if(isRunning){
MyRunnable myRunnable = null;
synchronized (lock){
myRunnable = taskQueue.poll();
if(myRunnable == null){
isNotify = true;
}
}
if(myRunnable!=null){
taskMap.put(mCachedThreadPool.submit(myRunnable),myRunnable);
}
}
}
});
}

public void releaseTask(){
Toast.makeText(this, "释放资源", Toast.LENGTH_SHORT).show();
mHandler.sendEmptyMessage(0);
Iterator<Map.Entry<Future, MyRunnable>> iterator = taskMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<Future,MyRunnable> entry = iterator.next();
Future future = entry.getKey();
if(future == null){
continue;
}
future.cancel(true);
taskMap.remove(future);//移除键对应的值
}
if(mCachedThreadPool!=null){
mCachedThreadPool.shutdown();//关闭执行器
}
mCachedThreadPool = null;
taskMap = null;
taskQueue = null;
}

public void notifyWork(){
synchronized (lock){
if(isNotify){
lock.notifyAll();
isNotify = !isNotify;
}
}
}
}

最后给出一篇写的比较好的关于线程池介绍的文章
​线程池的使用​​


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  qSqNY1UH2lvR   2023年11月02日   55   0   0 链路权重ide
  mrMLeSzj1mp0   2023年11月02日   29   0   0 文件名上传ide
  01BFOGI7NzGp   2023年11月02日   81   0   0 nginxluanginx location ifide
  Fv5flEkOgYS5   2023年11月02日   51   0   0 i++javaide
mrMLeSzj1mp0