参考安卓进阶之光第四章
目录
进程和线程的关系
- 进程是系统资源分配的最小单位,线程的系统调度的最小单位;
- 进程之间不能共享资源,线程之间可以共享所在进程的地址空间和资源;
- 一个进程中可以有多个线程,一个线程只能属于一个进程;
- 进程可以开启线程和其他进程;
- 线程都拥有各自的计数器,堆栈和局部变量等属性;
为什么使用多线程
- 可以把某一个耗时操作分配到一个单独的线程中去执行,减少程序响应时间;
- 线程创建和切换开销小,多线程在数据共享方面效率很高;
- 简化程序结构,使程序便于理解和维护;
线程的6种状态
- New:新创建状态,线程被创建,还没有调用start方法
- Runnable:可运行状态:调用start方法就处于这个状态,可能正在运行也可能没有运行,取决于操作系统;
- Blocked:阻塞状态:线程被锁阻塞,暂时不活动
- Waiting:等待状态,线程暂时不活动,并且不运行任何代码,等待线程调度器重新激活;
- Timed waiting:超时等待状态,在指定的时间自行返回
- Terminated:终止状态,当前线程已经执行完毕,线程终止的两种情况:run方法执行完毕或者异常终止
问题:sleep(),wait(),join()的区别和联系
- sleep是Thread的静态方法,使当前执行的线程休眠,把执行机会给其他线程,但只会让出CPU执行时间,不会释放锁,可以在任何地方使用;
- wait是Object里的一个方法,进入到一个与该对象相关的等待池中,同时释放对象锁,并让出CPU资源,待指定时间结束后得到对象锁,只能在同步方法或同步块中使用;
- join是将指定的线程加入到当前线程,并且等待到指定的线程执行完毕.比如,t.join(1000); //等待 t 线程,等待时间是1000毫秒。
顺便提一下yield:将线程转为就绪状态,且只会让优先级相同或者更高的线程有执行机会;
创建线程
问题:run和start的区别
- run只是Thread里面的一个普通方法,调用了run还是在主线程,start是启动子线程的方法
1.继承Thread类
Thread实现了Runnable接口的一个实例
调用start()只是使线程变为可运行态,并不一定立即地执行多线程的代码,什么时候运行是由操作系统决定的;
public class TestThread extends Thread{
@Override
public void run() {
super.run();
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread thread = new TestThread();
thread.start();
}
}
2.实现Runnable接口
public class TestThread1 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
TestThread1 testThread1 = new TestThread1();
Thread thread = new Thread(testThread1);
thread.start();
}
}
3.实现Callable接口,重写call()方法
Callable接口实际属于Executor框架中的功能类,比runnable提供了更强大的功能:
- 可以提供一个返回值
- call方法可以抛出异常
- 运行Callable可以拿到一个Future结果,future提供了检查计算是否完成的方法,但调用get()方法时,当前线程就是阻塞,知道call()方法返回结果;
public class TestThread2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyTestCallable myTestCallable = new MyTestCallable();
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future future = executorService.submit(myTestCallable);
System.out.println(future.get());
}
public static class MyTestCallable implements Callable{
@Override
public Object call() throws Exception {
return Thread.currentThread().getName();
}
}
}
中断
interrupt方法可以用来请求中断线程,调用interrupt方法时,线程的中断标志位将被标为true,线程会不断地检测这个标志位
使用中断来终止线程
public class StopThread {
public static void main(String[] args) throws InterruptedException {
MyRunner myRunner = new MyRunner();
Thread thread = new Thread(myRunner,"mythread");
thread.start();
//让主线程睡10ms,使子线程感知中断
TimeUnit.MILLISECONDS.sleep(10);
thread.interrupt();
}
public static class MyRunner implements Runnable{
private long i;
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()){
i++;
System.out.println("i=" + i + Thread.currentThread().getName() );
}
System.out.println("stop");
}
}
}
也可以采用boolean变量控制是否需要停止线程
public class StopThread {
public static void main(String[] args) throws InterruptedException {
MyRunner myRunner = new MyRunner();
Thread thread = new Thread(myRunner,"mythread");
thread.start();
//让主线程睡10ms,使子线程感知中断
TimeUnit.MILLISECONDS.sleep(10);
myRunner.cancel();
}
public static class MyRunner implements Runnable{
private long i;
private vo