目录
多线程编程对比: iOS与Android
android的多线程编程有
Thread
Handler
AsyncTask
IntentService
android多线程详细可以参考android学习 之 Service
iOS的多线程编程有
NSthread
GCD
NSOperationQueue
iOS多线程详细可以参考Objective-C学习 之 GCD / iOS最佳实践 之 优先使用NSOperationQueue而不是GCD / iOS开发 之 Queue和Thread
对比两个平台的多线程编程, android还是稍逊一些
Handler和IntentService的多线程编程, 开销有些大, 而GCD配合Block, 简洁好用并且功能也很强大
AsyncTask处理消息队列和多线程同步, 是比较费劲的, 而NSOperationQueue, 仍然是简单好用五颗星
那有没有一种方案可以让android变得和iOS一样简单好用呢?
答案就是今天的主角BoltsFramework/Bolts-Android
Bolts-Android
Bolts-Android由 因为作为Baas的鼻祖, Parse已经成功地死在了沙滩上, 但是被Facebook关门之后, 它仍然发挥了余热, Parse的很多项目都在Github Parse上开源了 废话不多说, 直接看例子吧 想要在当前线程执行Task, 就是这么简单 如果想在后台线程执行Task 如果想在UI主线程执行Task 如果想要延时执行Task 是不是简单到让人无法相信? 其实这里的Task和iOS中的GCD编程是类似的(详细可以参考Objective-C学习 之 GCD) 热完身, 我们来看下Bolts-Android的函数式编程(关于函数式编程详细可以参考谈谈函数式响应式编程(Functional Reactive Programming)) 打印结果如下 通过函数式的链式编程, 轻松地实现了Task的同步和多线程的切换(怎么忽然就想到了RxJava了呢? 看来下期可以来个Bolts-Android大战RxJava的专题) Group Task是我取得名字哈, 所谓Group Tasks, 就是指多个Task组成的一组Tasks 其中asyncOperation1和asyncOperation2的定义如下 后面的continueWith会等asyncOperation1和asyncOperation2都执行完成后再执行 打印结果如下 有没有小试牛刀的感觉? 我们接着来看下面的用法 打印结果如下 打印结果有两个发现 线程池有两个线程: pool-2-thread-1和pool-2-thread-2 线程池里的线程是并行执行的: 数字都是 那有没有方法可以让线程池中只有一个线程, 所有Tasks按照queue的方式FIFO依次执行呢? 办法如下 打印结果如下 看完上面的内容, 想必各位从此都是android多线程的"砖家"了吧, 不过请稍等片刻, 还有一个重要的问题没有解释 请问这里的打印结果是如何呢? A: onSuccess B: error C: done D: onSuccess & done 正确答案是B android多线程的方案还有诸如: yigit/android-priority-jobqueue, 不过经过实测, 和Bolts-Android比较起来, android-priority-jobqueue还是"略重量级"了一些, 如果你有更好的方案和实现, 欢迎留言和分享Tasks
Task.call(new Callable<Boolean>() { @Override
public Boolean call() throws Exception {
XLog.d(Thread.currentThread().getName() + " " + "call in current thread"); return true;
}
});
Task.callInBackground(new Callable<Boolean>() { @Override
public Boolean call() throws Exception {
XLog.d(Thread.currentThread().getName() + " " + "call in background thread"); return true;
}
});
Task.call(new Callable<Boolean>() { @Override
public Boolean call() throws Exception {
XLog.d(Thread.currentThread().getName() + " " + "call in main thread"); return true;
}
}, Task.UI_THREAD_EXECUTOR);
Task.delay(2000).continueWith(new Continuation<Void, Void>() { @Override
public Void then(Task<Void> task) throws Exception {
XLog.d(Thread.currentThread().getName() + " " + "call in main thread (after delay 2 seconds)"); return null;
}
});
Chaining Tasks
Task.call(new Callable<Boolean>() { @Override
public Boolean call() throws Exception {
XLog.d(Thread.currentThread().getName() + " calling"); return true;
}
}, Task.UI_THREAD_EXECUTOR).continueWith(new Continuation<Boolean, String>() { @Override
public String then(Task<Boolean> task) throws Exception {
Thread.sleep(2000);
XLog.d(Thread.currentThread().getName() + " onSuccess " + task.getResult()); return "hello bolts";
}
}, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation<String, Void>() { @Override
public Void then(Task<String> task) throws Exception {
XLog.d(Thread.currentThread().getName() + " continueWith " + task.getResult()); return null;
}
}, Task.UI_THREAD_EXECUTOR);
main calling
pool-2-thread-1 onSuccess truemain continueWith hello bolts
Group Tasks
Task.call(new Callable<Boolean>() { @Override
public Boolean call() throws Exception {
XLog.d(Thread.currentThread().getName() + " calling"); return true;
}
}, Task.UI_THREAD_EXECUTOR).continueWith(new Continuation<Boolean, List<Task<Void>>>() { @Override
public List<Task<Void>> then(Task<Boolean> task) throws Exception {
XLog.d(Thread.currentThread().getName() + " tasks start");
List<Task<Void>> tasks = new ArrayList<Task<Void>>();
tasks.add(asyncOperation1());
tasks.add(asyncOperation2());
Task.whenAll(tasks).waitForCompletion();
XLog.d(Thread.currentThread().getName() + " tasks end"); return tasks;
}
}, Task.BACKGROUND_EXECUTOR).continueWith(new Continuation<List<Task<Void>>, Void>() { @Override
public Void then(Task<List<Task<Void>>> task) throws Exception {
XLog.d(Thread.currentThread().getName() + " done"); return null;
}
}, Task.UI_THREAD_EXECUTOR);
private Task<Void> asyncOperation1() { return Task.callInBackground(new Callable<Void>() { @Override
public Void call() throws Exception {
XLog.i("asyncOperation1 start"); try {
Thread.sleep(1000);
} catch (Exception e) {
XLog.e(e.getMessage());
}
XLog.i("asyncOperation1 end"); return null;
}
});
}private Task<Void> asyncOperation2() { return Task.callInBackground(new Callable<Void>() { @Override
public Void call() throws Exception {
XLog.i("asyncOperation2 start"); try {
Thread.sleep(3000);
} catch (Exception e) {
XLog.e(e.getMessage());
}
XLog.i("asyncOperation2 end"); return null;
}
});
}
main calling
pool-2-thread-1 tasks start
asyncOperation1 start
asyncOperation2 start
asyncOperation1 end
asyncOperation2 end
pool-2-thread-1 tasks end
main done
Tasks in Parallel
final Executor PARALLEL_EXECUTOR = Executors.newCachedThreadPool();
Task.call(new Callable<Void>() { @Override
public Void call() throws Exception { for (int i = 0; i < 100; i++) { if (i % 2 == 0) {
XLog.i(Thread.currentThread().getName() + " i = " + i);
}
} return null;
}
}, PARALLEL_EXECUTOR);
Task.call(new Callable<Void>() { @Override
public Void call() throws Exception { for (int i = 0; i < 100; i++) { if (i % 2 == 1) {
XLog.i(Thread.currentThread().getName() + " i = " + i);
}
} return null;
}
}, PARALLEL_EXECUTOR);
pool-2-thread-1 i = 0
pool-2-thread-2 i = 50
pool-2-thread-1 i = 1
pool-2-thread-2 i = 51
pool-2-thread-1 i = 2
pool-2-thread-2 i = 52
pool-2-thread-1 i = 3
pool-2-thread-2 i = 53
pool-2-thread-1 i = 4
pool-2-thread-2 i = 54
pool-2-thread-1 i = 5
pool-2-thread-1 i = 6
pool-2-thread-2 i = 55
pool-2-thread-2 i = 56
pool-2-thread-1 i = 7
pool-2-thread-1 i = 8
pool-2-thread-2 i = 57
pool-2-thread-2 i = 58
pool-2-thread-1 i = 9
pool-2-thread-2 i = 59
pool-2-thread-1 i = 10
pool-2-thread-2 i = 60
pool-2-thread-1 i = 11
pool-2-thread-2 i = 61
pool-2-thread-1 i = 12
pool-2-thread-2 i = 62
pool-2-thread-1 i = 13
pool-2-thread-2 i = 63
pool-2-thread-1 i = 14
pool-2-thread-2 i = 64
pool-2-thread-1 i = 15
pool-2-thread-2 i = 65
pool-2-thread-1 i = 16
pool-2-thread-2 i = 66
pool-2-thread-1 i = 17
pool-2-thread-2 i = 67
pool-2-thread-1 i = 18
pool-2-thread-1 i = 19
pool-2-thread-2 i = 68
pool-2-thread-1 i = 20
pool-2-thread-2 i = 69
pool-2-thread-1 i = 21
pool-2-thread-2 i = 70
pool-2-thread-1 i = 22
pool-2-thread-2 i = 71
pool-2-thread-1 i = 23
pool-2-thread-2 i = 72
pool-2-thread-1 i = 24
pool-2-thread-2 i = 73
pool-2-thread-2 i = 74
pool-2-thread-1 i = 25
pool-2-thread-2 i = 75
pool-2-thread-1 i = 26
pool-2-thread-2 i = 76
pool-2-thread-1 i = 27
pool-2-thread-2 i = 77
pool-2-thread-1 i = 28
pool-2-thread-2 i = 78
pool-2-thread-1 i = 29
pool-2-thread-2 i = 79
pool-2-thread-1 i = 30
pool-2-thread-1 i = 31
pool-2-thread-2 i = 80
pool-2-thread-1 i = 32
pool-2-thread-2 i = 81
pool-2-thread-1 i = 33
pool-2-thread-2 i = 82
pool-2-thread-1 i = 34
pool-2-thread-2 i = 83
pool-2-thread-2 i = 84
pool-2-thread-1 i = 35
pool-2-thread-2 i = 85
pool-2-thread-1 i = 36
pool-2-thread-2 i = 86
pool-2-thread-1 i = 37
pool-2-thread-2 i = 87
pool-2-thread-1 i = 38
pool-2-thread-1 i = 39
pool-2-thread-2 i = 88
pool-2-thread-1 i = 40
pool-2-thread-2 i = 89
pool-2-thread-1 i = 41
pool-2-thread-2 i = 90
pool-2-thread-1 i = 42
pool-2-thread-2 i = 91
pool-2-thread-1 i = 43
pool-2-thread-2 i = 92
pool-2-thread-1 i = 44
pool-2-thread-2 i = 93
pool-2-thread-1 i = 45
pool-2-thread-2 i = 94
pool-2-thread-1 i = 46
pool-2-thread-2 i = 95
pool-2-thread-1 i = 47
pool-2-thread-2 i = 96
pool-2-thread-1 i = 48
pool-2-thread-2 i = 97
pool-2-thread-1 i = 49
pool-2-thread-2 i = 98
pool-2-thread-2 i = 99
Tasks in Serial
final Executor SERIAL_EXECUTOR = Executors.newSingleThreadExecutor();
Task.call(new Callable<Void>() { @Override
public Void call() throws Exception { for (int i = 0; i < 50; i++) {
XLog.i(Thread.currentThread().getName() + " i = " + i);
} return null;
}
}, SERIAL_EXECUTOR);
call(new Callable<Void>() { @Override
public Void call() throws Exception { for (int i = 50; i < 100; i++) {
XLog.i(Thread.currentThread().getName() + " i = " + i);
} return null;
}
}, SERIAL_EXECUTOR);
pool-2-thread-1 i = 0
pool-2-thread-1 i = 1
pool-2-thread-1 i = 2
pool-2-thread-1 i = 3
pool-2-thread-1 i = 4
pool-2-thread-1 i = 5
pool-2-thread-1 i = 6
pool-2-thread-1 i = 7
pool-2-thread-1 i = 8
pool-2-thread-1 i = 9
pool-2-thread-1 i = 10
pool-2-thread-1 i = 11
pool-2-thread-1 i = 12
pool-2-thread-1 i = 13
pool-2-thread-1 i = 14
pool-2-thread-1 i = 15
pool-2-thread-1 i = 16
pool-2-thread-1 i = 17
pool-2-thread-1 i = 18
pool-2-thread-1 i = 19
pool-2-thread-1 i = 20
pool-2-thread-1 i = 21
pool-2-thread-1 i = 22
pool-2-thread-1 i = 23
pool-2-thread-1 i = 24
pool-2-thread-1 i = 25
pool-2-thread-1 i = 26
pool-2-thread-1 i = 27
pool-2-thread-1 i = 28
pool-2-thread-1 i = 29
pool-2-thread-1 i = 30
pool-2-thread-1 i = 31
pool-2-thread-1 i = 32
pool-2-thread-1 i = 33
pool-2-thread-1 i = 34
pool-2-thread-1 i = 35
pool-2-thread-1 i = 36
pool-2-thread-1 i = 37
pool-2-thread-1 i = 38
pool-2-thread-1 i = 39
pool-2-thread-1 i = 40
pool-2-thread-1 i = 41
pool-2-thread-1 i = 42
pool-2-thread-1 i = 43
pool-2-thread-1 i = 44
pool-2-thread-1 i = 45
pool-2-thread-1 i = 46
pool-2-thread-1 i = 47
pool-2-thread-1 i = 48
pool-2-thread-1 i = 49
pool-2-thread-1 i = 50
pool-2-thread-1 i = 51
pool-2-thread-1 i = 52
pool-2-thread-1 i = 53
pool-2-thread-1 i = 54
pool-2-thread-1 i = 55
pool-2-thread-1 i = 56
pool-2-thread-1 i = 57
pool-2-thread-1 i = 58
pool-2-thread-1 i = 59
pool-2-thread-1 i = 60
pool-2-thread-1 i = 61
pool-2-thread-1 i = 62
pool-2-thread-1 i = 63
pool-2-thread-1 i = 64
pool-2-thread-1 i = 65
pool-2-thread-1 i = 66
pool-2-thread-1 i = 67
pool-2-thread-1 i = 68
pool-2-thread-1 i = 69
pool-2-thread-1 i = 70
pool-2-thread-1 i = 71
pool-2-thread-1 i = 72
pool-2-thread-1 i = 73
pool-2-thread-1 i = 74
pool-2-thread-1 i = 75
pool-2-thread-1 i = 76
pool-2-thread-1 i = 77
pool-2-thread-1 i = 78
pool-2-thread-1 i = 79
pool-2-thread-1 i = 80
pool-2-thread-1 i = 81
pool-2-thread-1 i = 82
pool-2-thread-1 i = 83
pool-2-thread-1 i = 84
pool-2-thread-1 i = 85
pool-2-thread-1 i = 86
pool-2-thread-1 i = 87
pool-2-thread-1 i = 88
pool-2-thread-1 i = 89
pool-2-thread-1 i = 90
pool-2-thread-1 i = 91
pool-2-thread-1 i = 92
pool-2-thread-1 i = 93
pool-2-thread-1 i = 94
pool-2-thread-1 i = 95
pool-2-thread-1 i = 96
pool-2-thread-1 i = 97
pool-2-thread-1 i = 98
pool-2-thread-1 i = 99
Error Handling
Task.call(new Callable<String>() { @Override
public String call() throws Exception {
Thread.sleep(2000); if (1 < 10) {
XLog.d(Thread.currentThread().getName() + " RuntimeException"); throw new RuntimeException("There was an error.");
} return "hello bolts";
}
}, Task.BACKGROUND_EXECUTOR).onSuccess(new Continuation<String, Void>() { @Override
public Void then(Task<String> task) throws Exception {
XLog.d(Thread.currentThread().getName() + " onSuccess"); return null;
}
}, Task.UI_THREAD_EXECUTOR).continueWith(new Continuation<Void, Void>() { @Override
public Void then(Task<Void> task) throws Exception { if (task.isFaulted()) {
XLog.e(Thread.currentThread().getName() + " error"); return null;
}
XLog.d(Thread.currentThread().getName() + " done"); return null;
}
}, Task.UI_THREAD_EXECUTOR);
小结
作者:诺之林
链接:https://www.jianshu.com/p/fcfb541568af
共同學習,寫下你的評論
評論加載中...
作者其他優質文章