文章目录
创建新线程
继承Thread类重写run方法
package example;
public class Work extends Thread {
@Override
public void run() {
super.run();
System.out.println("new thread start");
}
}
也可以直接写在创建处
package example;
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
super.run();
System.out.println("new thread start");
}
};
thread.start();
}
}
用Lambda表达式可以简写这一过程
package example;
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("new thread start");
});
thread.start();
}
}
实现 Runnable 接口,重写 run 方法,作为参数传入Thread()
package example;
public class Work implements Runnable {
@Override
public void run() {
System.out.println("new thread start");
}
}
或者直接在参数里创建
package example;
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("new thread start");
}
});
thread.start();
}
}
Thread 构造方法参数
private Thread(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals)
- ThreadGroup g:线程组
- Runnable target:要执行的任务
- String name:线程名
Thread 常用方法
currentThread()
静态方法,返回对当前正在执行的线程对象的引用
start()
在原线程执行,启动新线程,接着会在新线程内自动执行 run() 方法,一个线程只能执行一次 start()
方法
yield()
指当前线程愿意让出对当前处理器的占用
sleep()
静态方法,使当前线程挂起一段时间
join()
使当前线程等待另一个线程执行完毕之后再继续执行
setPriority(int n)
静态方法,设置线程的优先级,供操作系统调度使用
线程的状态
- New:新创建的线程,尚未执行;
- Runnable:运行中的线程,正在执行
run()
方法的Java代码; - Blocked:运行中的线程,因为某些操作被阻塞而挂起;
- Waiting:运行中的线程,因为某些操作在等待中;
- Object.wait():使当前线程处于等待状态直到另一个线程唤醒它;
- Thread.join():等待线程执行完毕,底层调用的是Object实例的wait方法;
- LockSupport.park():除非获得调用许可,否则禁用当前线程进行线程调度。
- Timed Waiting:运行中的线程,因为执行
sleep()
方法正在计时等待;- Thread.sleep(long millis):使当前线程睡眠指定时间;
- Object.wait(long timeout):线程休眠指定时间,等待期间可以通过
notify()/notifyAll()
唤醒; - Thread.join(long millis):等待当前线程最多执行
millis
毫秒,如果millis
为0,则会一直执行; - LockSupport.parkNanos(long nanos): 除非获得调用许可,否则禁用当前线程进行线程调度指定时间;
- LockSupport.parkUntil(long deadline):同上,也是禁止线程进行调度指定时间;
- Terminated:线程已终止,因为
run()
方法执行完毕。
可以使用 getState()
方法查看线程状态,这个方式只是给用户提供一个查看线程状态的方法,并不能用来进行线程同步控制
package example;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("new thread start");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
System.out.println(thread.getState());
//NEW
thread.start();
System.out.println(thread.getState());
//RUNNABLE
Thread.sleep(1000);
System.out.println(thread.getState());
//TIMED_WAITING
thread.join();
System.out.println(thread.getState());
//TERMINATED
}
}
守护线程
对于一般线程,如果线程没有结束,那么JVM就不会结束
而对于守护线程,当所有非守护线程结束,就算守护线程没结束,JVM也会结束
守护线程需要在线程启动前,由线程的引用调用 setDaemon(true)
来设置
package example;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
try {
Thread.sleep(100000);
System.out.println("after sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.setDaemon(true);
thread.start();
}
}
运行程序会发现程序立即结束,没有打印任何信息,显然程序并没有等待守护线程结束
中断线程
使用 interrupt() 方法通知线程结束
对于线程 t,其他线程如果调用 t.interrupt()
方法,在线程 t 内,isInterrupted()
就会返回true,通知线程结束操作
如果线程处于等待,如在调用 join()
等待其他线程执行,join
会抛出 InterruptedException
异常,此时只要捕获到该异常,也就收到了结束线程的通知
使用共享变量通知
在线程内,可以定义一个共享变量,供其他线程使用通知结束信号
public volatile boolean interupt = false;
volatile 关键字告诉JVM要立刻更新内存中的信息