两种基本的创建线程方式
最基本的创建方式,我们通过实现Runnable接口,或者继承自Thread类,覆写run方法。
- 继承Thread类,覆写run方法
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val taskOne = MyThreadTask()
taskOne.name = "thread-1"
taskOne.start()
val taskTwo = MyThreadTask()
taskTwo.name = "thread-2"
taskTwo.start()
}
class MyThreadTask:Thread(){
override fun run() {
println("当前线程为 -- > " + Thread.currentThread().name)
}
}
运行结果:
I/System.out: 当前线程为 -- > thread-2
I/System.out: 当前线程为 -- > thread-1
- 实现Runnable接口,实现run方法
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val threadOne = Thread(MyTask())
threadOne.name = "thread one"
threadOne.start()
val threadTwo = Thread(MyTask())
threadTwo.name = "thread two"
threadTwo.start()
}
class MyTask : Runnable {
override fun run() {
println("当前线程为 -- > " + Thread.currentThread().name)
}
}
}
运行结果
I/System.out: 当前线程为 -- > thread one
I/System.out: 当前线程为 -- > thread two
这两种创建方式的区别
这两种创建方式最主要的区别是实现Runnable接口的方式创建,可以给多个Thread用,这样子的话可以共享数据。但是也要注意线程安全问题。
如果使用继承Thread的方式创建,则无法共享数据。
推荐使用实现Runnable实现run方法的方式去创建线程。
AsyncTask
有些同学可以没有听过AsyncTask,现在基本上不使用了,同学们了解一下就行。
AsyncTask是一个轻量级的异步任务执行工具
AsyncTask enables proper and easy use of the UI thread.
第一种创建方式:
class AsyncTaskMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val downloadTask = DownloadTask()
downloadTask.execute("https://www.sunofbeach.net/download/test")
}
class DownloadTask : AsyncTask<String, Int, String>() {
/**
* 此为后台执行程序
*/
override fun doInBackground(vararg params: String?): String {
//做下载动作
for (i in 0 until 100) {
//进度通知
publishProgress(i)
}
return "请求 -- > ${params[0]} 成功...."
}
override fun onPostExecute(result: String?) {
//结果处理
println(result)
}
override fun onProgressUpdate(vararg values: Int?) {
//进度更新
println("当前进度 -- > " + values[0])
}
}
}
运行结果:
I/System.out: 当前进度 -- > 0
I/System.out: 当前进度 -- > 1
I/System.out: 当前进度 -- > 2
I/System.out: 当前进度 -- > 3
...
I/System.out: 当前进度 -- > 98
I/System.out: 当前进度 -- > 99
I/System.out: 请求 -- > https://www.sunofbeach.net/download/test 成功....
AsyncTask的缺点:默认使用串行的线程池执行任务。
也就是说,如果往这个池里创建10AsyncTask任务,有一个一直没结束,比如说阻塞,休眠,那么其他的就无法执行了。
所以我们使用的时候,要把Executor设置为并行的。
downloadTask.executeOnExecutor(
AsyncTask.THREAD_POOL_EXECUTOR,
"https://www.sunofbeach.net/download/test"
)
第二种创建方式:
直接执行Runnable接口实现类(串行执行)
AsyncTask.execute {
println("Async task running ... " + Thread.currentThread().name)
}
执行结果:
I/System.out: Async task running ... AsyncTask #1
修改成并行的执行方式
AsyncTask.THREAD_POOL_EXECUTOR.execute {
println("Async task running ... " + Thread.currentThread().name)
}
这样子呢,就可以并发地执行了,如果多个任务的话。
这两种创建方式的区别很明显。前者可以知道结果,方便管理和控制。
HandlerThread
HandlerThread适用于轮询场景,通过发送消息的形式执行任务,这也是一个串行的执行方式。
class HandlerThreadMainActivity : AppCompatActivity() {
companion object {
const val MSG_ONE = 1
const val MSG_TWO = 2
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val handlerThread = HandlerThread("thread-#1")
//开始轮询
handlerThread.start()
//绑定handler处理消息
val taskHandler = TaskHandler(handlerThread.looper)
//主线程发送消息
println("主线程发送消息..")
taskHandler.sendEmptyMessage(MSG_ONE)
val message = taskHandler.obtainMessage()
message.what = MSG_TWO
message.obj = "this is object that anything you want to send..."
taskHandler.sendMessage(message)
}
class TaskHandler(looper: Looper) : Handler(looper) {
override fun handleMessage(msg: Message) {
when (msg.what) {
MSG_ONE -> {
//TODO:
println("MSG_ONE =- > " + Thread.currentThread().name)
}
MSG_TWO -> {
//TODO:
println("MSG_TWO =- > " + Thread.currentThread().name)
println(msg.obj)
}
}
}
}
}
这个用得比较少,一般是主线程的Handler用得比较多。在子线程给主线程发送消息。
比如说我们在子线程请求数据,然后向主线程发送结果。
另外,HandlerThread构造方法,有多个重载方法,还可以传入优先级。不传则为默认优先级。
IntentService
IntentService是个服务,它可以于后台运行。常用于我们需要跨界面获取到后台任务执行进度,比如说我们上传东西,下载东西。
它执行完任务则会结束服务。
class TaskIntentService : IntentService("server-thread-one") {
override fun onHandleIntent(intent: Intent?) {
val targetUrl = intent!!.getStringExtra("url")
println("do download url -- > $targetUrl")
val total = 100
for (i in 0 until total) {
Thread.sleep(100)
sendProgress(i, total)
}
println("task completed...")
}
private fun sendProgress(currentProgress: Int, totalProgress: Int) {
val intent = Intent("net.sunofbeach.action.serviceProgress")
intent.putExtra("current", currentProgress)
intent.putExtra("total", totalProgress)
sendBroadcast(intent)
}
override fun onDestroy() {
super.onDestroy()
println("on service destroy...")
}
}
执行结果:
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
I/System.out: do download url -- > https://www.sunofbeach.net/download/test
I/OpenGLRenderer: Initialized EGL, version 1.4
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
D/EGL_emulation: eglCreateContext: 0xae5544e0: maj 2 min 0 rcv 2
D/EGL_emulation: eglMakeCurrent: 0xae5544e0: ver 2 0 (tinfo 0xae5528b0)
D/EGL_emulation: eglMakeCurrent: 0xae5544e0: ver 2 0 (tinfo 0xae5528b0)
I/System.out: task completed...
I/System.out: on service destroy...
ThreadPoolExecutor
线程池的话重复使用线程,减少线程创建和销毁的开销。使用于频繁的,消耗资源相对少的操作。
然后把任务扔到池里执行
class ThreadPoolMainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val task = Task()
//线程可以复用的线程池
val newCachedThreadPool = Executors.newCachedThreadPool()
newCachedThreadPool.execute(task)
//只有一个线程的任务池
val newSingleThreadExecutor = Executors.newSingleThreadExecutor()
newSingleThreadExecutor.execute(task)
}
class Task : Runnable {
override fun run() {
println("doing task...")
}
}
}
其他的线程池请查看文档吧。当然啦,也可以自定义线程池