一、线程:
1、线程和进程:
进程:是系统进行资源分配的基本单位,例如Window管理器中某个exe程序:qq.exe、studio.exe。在android系统中,一般表示的是一个应用程序,例如邮件、相机等应用。
线程:操作系统调度的最小单位,比如多个线程有的请求数据,有的更新ui,有的操作数据库。线程拥有各自的计数器、堆栈、局部变量等。
线程的意义:如果所有操作都在一个线程执行,会导致效应速度慢,效率低。如果将耗时操作放在其他线程中执行,减少了主线程响应时间,会有更好的交互。
进程和线程的关系:一个进程有多个线程,一个应用可以开启多个线程进行工作。
2、线程的状态:
- New: 创建状态,线程刚创建,还没有调用start方法。
- Runnable:可运行状态,调用了start方法后线程在执行run方法且没有阻塞时状态为Runnable,不过,Runnable不代表CPU一定在执行该线程的代码,可能正在执行也可能在等待操作系统分配时间片。
- Blocked: 阻塞状态,表示该线程被锁阻塞。例如其他线程持有锁,该线程在等待其他线程将锁释放。
- Waiting:等待状态,线程没运行任何代码,需要线程调度器重新激活。例如线程A调用wait方法进行等待,这时候需要其他线程调用notify或notifyAll方法激活线程A。
- Timed waiting:超时等待状态,和等待状态的区别:在等待指定时间后自动激动。
- Terminated:终止状态,当前线程执行完毕。比如run方法执行完了,或者执行过程中遇到异常终止线程。
3、常用方法:
(1)获取id和name:
public long getId()public final String getName()复制代码
(2)获取和设置优先级:
public final void setPriority(int newPriority)public final int getPriority()复制代码
(3)会让当前线程睡眠指定的时间,单位是毫秒。 睡眠期间,该线程会让出CPU, 睡眠期间,线程可以被中断,如果被中断,sleep会抛出InterruptedException。
public static native void sleep(long millis) throws InterruptedException;
复制代码
(4)让调用join的线程等待该线程结束, 在等待线程结束的过程中,这个等待可能被中断,如果被中断,会抛出InterruptedException。
public final void join() throws InterruptedException
复制代码
(5)wait:
public final void wait() throws InterruptedException
public final native void wait(long timeout) throws InterruptedException;复制代码
- 把当前线程放入条件等待队列,释放对象锁,阻塞等待,线程状态变为WAITING或TIMED_WAITING
- 等待时间到或被其他线程调用notify/notifyAll从条件队列中移除,这时,要重新竞争对象锁
-
- 如果能够获得锁,线程状态变为RUNNABLE,并从wait调用中返回
- 否则,该线程加入对象锁等待队列,线程状态变为BLOCKED,只有在获得锁后才会从wait调用中返回
(6)notify/notifyAll:
public final native void notify();
public final native void notifyAll();
复制代码
notify就是从条件队列中选一个线程,将其从队列中移除并唤醒,notifyAll会移除条件队列中所有的线程并全部唤醒。
(7)interrupted方法:
注:停止一个线程的主要机制是中断,中断并不是强迫终止一个线程,它是一种协作机制,是给线程传递一个取消信号,但是由线程来决定如何以及何时退出。
public boolean isInterrupted()
public void interrupt()
public static boolean interrupted()
复制代码
- isInterrupted:返回对应线程的中断标志位是否为true。
- interrupted:返回当前线程的中断标志位是否为true,还有就是清空中断标志位。也就是说,连续两次调用interrupted(),第一次返回的结果为true,第二次一般就是false
- interrupt:表示请求中断对应的线程,此时线程中断标志位置为true,线程会不断检测此标志位。
线程自身处理中断:
public class MyRunnable implements Runnable{
int i = 0;
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()){
System.out.print(++i);
}
//如果线程执行中调用interrupt方法,输出然后结束
System.out.print("interrupt");
}
}复制代码
二、线程创建:
1、继承Thread类,重写run方法:
class Thread implements Runnable {复制代码
Thread内部实现了Runnable接口
public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.print(getName());
}
}
复制代码
MyThread thread = new MyThread();
thread.start();复制代码
创建Thread子类实例,然后调用start方法
2、实现runnable接口,实现run方法
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.print("hello");
}
}复制代码
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();复制代码
- 实现Runnable接口,实现run方法
- 创建Thread实例对象,将实现了Runnable的实例对象以参数形式传入
- 调用Thread对象的start方法
3、实现Callable接口,实现call方法:
public class MyCallback implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return 2;
}
}复制代码
MyCallback callback = new MyCallback();
Future<Integer> future = Executors.newSingleThreadExecutor().submit(callback);
try {
System.out.print(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}复制代码
- 实现Callback接口,实现run方法
- 实例化MyCallback对象,通过参数的形式传递给ExecutorService的submit方法
- 最终通过调用Future的get方法获取到任务执行完毕的返回值
Future对象:
public interface Future<V> {
boolean cancel(boolean var1);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException;
}复制代码
- 运行 Callable 任务可以拿到一个 Future 对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过 Future 对象可以了解任务执行情况,可取消任务的执行,还可获取执行结果;
Runnable和Callable的区别:
- Callable 接口下的方法是 call(),Runnable 接口的方法是 run();
- Callable 的任务执行后可返回值,而 Runnable 的任务是不能返回值的;
- call() 方法可以抛出异常,run()方法不可以的;
总结:一般需要返回值,比如在线程中读取数据库数据,可以用Callback创建线程,如果不需要返回值,比如写入数据库,可以使用Thread或Runnable去创建线程。