多线程与Android线程性能优化(二)

771 阅读3分钟

认识Java里的线程

Java里的程序天生就是多线程的

可以通过如下代码获取Java中默认的线程

    public static void main(String[] args) {
        /*虚拟机线程管理的接口*/
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        /*取得线程信息*/
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        for (ThreadInfo threadInfo : threadInfos) {
            System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName());
        }
    }

结果如下

[5] Monitor Ctrl-Break //监控Ctrl-Break中断信号的线程
[4] Signal Dispatcher //分发处理发送给JVM信号的线程
[3] Finalizer //调用对象finalize方法的线程
[2] Reference Handler //清除Reference的线程
[1] main //线程,用户程序入口

线程的启动与终止

启动方式

  • X extend Thread;然后X.run
  • X implement Runnable; 然后交给Thread执行
  • X implement Callable;然后交给FutureTask后再交给Thread执行

1、直接集成Thread

object NewThread {
    private class WorkThread: Thread() {
        override fun run() {
            super.run()
            println("do work on thread: ${currentThread().name}")
        }
    }

    @JvmStatic
    fun main(args: Array<String>) {
        WorkThread().start()
    }
}

2、实现Runnable接口

object NewThread {

    private class WorkThread1: Runnable {
        override fun run() {
            println("do work1 implement runnable on thread: ${currentThread().name}")
        }
    }

    @JvmStatic
    fun main(args: Array<String>) {
        Thread(WorkThread1()).start()
    }
}

3、实现Callable接口

object NewThread {

    private class WorkThread2: Callable<String> {
        override fun call(): String {
            println("do work2 implement callable on thread: ${currentThread().name}")
            return "WorkThread2 do finished"
        }
    }

    @JvmStatic
    fun main(args: Array<String>) {
        val futureTask = FutureTask(WorkThread2())
        Thread(futureTask).start()
        //获取执行结果
        val result = futureTask.get()
        println("result: $result")
    }
}

FutureTask实现了RunnableFuture接口,而RunnableFuture接口又继承了Runable接口和Future接口,所以,第三种线程创建方式实际上跟第二种是一样的,不过由于同时继承了Future接口,所以可以获取返回的结果。

线程的中止

线程的自然中止:线程run方法执行完成,或者抛出了一个未处理的异常导致线程提前结束

手动中止:

stop() 该方法已经废弃,不建议使用了,因为它会引发安全问题。比如,一个线程正在执行数据写入操作,若此时调用了stop方法,那么数据就会出问题等。

interrupt() 安全的中止,该方法表示通知线程要中断了,但线程是否真正中断取决于内部实际的操作,在线程中可以通过调用isInterrupt()方法来判断是否被中断.

如果一个线程处于了阻塞状态(线程调用了sleep、join、wait等方法),则线程在检查中断标识时如果发现中断标志位为true,线程会在这些阻塞方法调用的地方抛出InterruptException异常,并且会清除中断标志位,重新设置为false,可以在异常后再次调用interrupt()方法,来进行中断

线程的状态

  1. 初始态(NEW): 新创建了一个线程对象,还没有调用start()方法
  2. 运行态:Java线程中将就绪(ready)和运行中(running)统称为运行态
线程对象创建后,并调用了start方法,该状态的线程位于可运行的线程池中,等待被线程调度选中,获取CPU的使用权,
此时处于ready状态,就绪状态的线程在获得CPU使用权后就变成了running状态
  1. 阻塞(BLOCKED): 表示线程被锁住了
  2. 等待(WAITING): 进入该状态的线程需要等待其他线程做出一些特定动作(通知notify或者中断interrupt)
  3. 超时等待(TIMED_WAITING): 该状态可以在指定时间后自行返回
  4. 终止(TERMINATED): 表示线程执行完毕

线程状态图

线程的其他方法

yield:使当前线程让出CPU占有权,但让出的时间是不可设定的,也不会释放锁资源,所有执行yield方法的线程有可能在进入到可执行状态后马上又被执行。

join: