Java 线程基本操作
实现方式
-
实现
Runable
接口的run
方法public static class RunnableTask implements Runnable { // 注意此处返回类型是void,Runnable接口没有返回值 @Override public void run(){ // do something } public static void main(String[] args) throws InterruptedException{ RunableTask task = new RunnableTask(); //启动线程 new Thread(task).start(); new Thread(task).start(); } }
-
继承
Thread
并重写run
方法public class ThreadTest { //该类不能继承其他类 public class MyThread extend Thread { @Override public void run(){ //do something } } public static void main(String[] args) { MyThread myThread = new MyThread(); //启动线程 thread.start(); } }
-
使用
FutureTask
public static class CallerTask implements Callable<String> { // 注意此处返回类型是void,Runnable接口没有返回值 @Override public String call() throws Exception{ // do something return "result"; } public static void main(String[] args) throws InterruptedException{ // 包装 Callable 用于接受返回值 FutureTask<String> task = new FutureTask<>(new CallerTask()); // 启动线程 new Thread(task).start(); try { String result = futureTask.get(); } catch (ExceptionException e) { e.printStackTrace(); } } }
线程的基本操作
[共享变量].wait()
调用线程会被挂起,并且释放该共享变量的锁资源,直至:
- 其他线程调用该共享变量的
notify()
或notifyAll()
方法 - 其他线程调用该线程
interrupt()
方法,线程抛出InterruptedException
异常返回
一个线程可能会被虚假唤醒(没有被其他线程唤醒 ( notify / notifyAll) 或被中断)
可以通过对线程执行条件进行检查
synchronize(obj) { while (条件不满足) { //例如生产者可以判定 while (queue.size == MAX_SIZE) obj.wait(); } }
相似函数:
wait(long timeout)
:由超时时间参数
``wait(long timeout, int nanos)`:在 nanos > 0 时,是参数 timeout 递增 1
[共享变量].notify()
相似函数:notifyAll()
调用后,会随机唤醒一个在共享变量上调用wait()
方法挂起的线程
被唤醒的线程不会马上从wait()
返回,需要获得锁后才可以返回
相似函数:
notifyAll()
:会唤醒共享变量等待集合中的所有线程
[线程].join()
当前线程 等待 调用join()的线程 任务执行完成
[线程].sleep()
调用线程暂时让出指定时间的执行权,不参与 CPU 调度,但是该线程拥有的锁资源不让出
调用线程会处于挂起阻塞态
[线程].yield()
线程请求调度器让出自己的 CPU 使用,让出成功则处于就绪态
线程中断
设置线程的中断标志不能终止线程运行,而是被中断的线程根据中断状态自行进行处理
-
void interrupt()
:设置中断标志位为 true;若线程调用
wait()
、sleep()
、join()
方法被阻塞挂起,会抛出InterruptedException
异常 -
boolean isInterrupted()
:检查当前线程是否被中断 -
static boolean interrupted()
:检测当前线程是否被中断,若被中断,则会清除中断标志。
static boolean interrupted()
和 void interrupt()
区分
interrupt()
是调用线程的标志位。
isInterrupted()
是当前线程的标志位(并非调用线程)。
public static void main(String[] args) throws InterruptedException{
Thread threadOne = new Thread(new Runnable() {
public void run() {while(true);}
});
threadOne.start();
threadOne.interrupt();
threadOne.isInterrupted(); //true,调用线程是 threadOne
threadOne.interrupted(); //false,当前线程是主线程
Thread.interrupted(); //false,当前线程是主线程
}