线程的基础知识扫盲
线程的创建方式
-
集成Thread类
class MyJob extend Thread{ public void run(){ // todo 业务代码 } } public static void main(String[] args){ MyJob my = new MyJob(); my.start(); }
-
实现Runnable接口
class MyJob implements Runable{ public void run(){ // todo 业务代码 } } public static void main(String[] args){ MyJob my = new MyJob(); Thread t = new Thread(my); t.start(); }
-
实现Callable接口,重写call方法,开启带有返回值的线程,通常配合FutureTask(同步非阻塞)类使用
class MyJob implements Callable{ public Object call(){ return value; } } public static void main(String[] args){ MyJob my = new MyJob(); FutureTask f = new FutureTask(my); Thread t = new Thread(f); t.start(); // todo 其他需要同步执行的功能 Object o = f.get();// 获得返回值 }
线程的状态
传统的线程状态有五种
Java 中Thread类中有六种线程状态
线程的常用方法
- 获取当前线程信息
Thread t = Thread.currentThread();
- 设置线程名称,方便出错时进行错误定位
Thread t = new Thread(()->{
});
t.setName("自定义的线程名称");
t.start();
- 设置线程优先级,其实就是CPU调度线程的优先级,最大值10,最小值1,默认值5
Thread t = new Thread(()->{
});
t.setPriority(1<=数值<=10);
t.start();
- 线程的让步,通过Thread的yield(),让当前线程从运行状态变为就绪状态,至于是否会被cpu执行不确定,需要等cpu的调度
Thread.yield();
- 线程的休眠sleep(long millis),让线程从运行状态变为等待状态(阻塞状态)
Thread.sleep(1000);// 线程休眠1s
- 线程的强占调用Thread的非静态方法join(),需要在某一个具体的线程下去调用。Thread
Thread t1 = new Thread(()->{
});
Thread t2 = new Thread(()->{
});
t1.start();
t2.start();
// 不加参数时,标示t2线程进入等待状态,需要等t1线程执行完,
// t2线程才会进入就绪状态,等待CPU调度
t1.join();
// t1 强占2s,t2进入等待状态,等t1线程执行完,
// t2线程才会进入就绪状态,等待CPU调度
// 若在等待期间,t1执行完毕,无需等待2s,t2进入就绪状态,等待CPU调度,
t1.join(2000);
- 守护线程,默认情况下线程都是非守护线程,即没有守护线程时,JVM会被结束掉,主线程默认是非守护线程,开启守护线程需设置当前线程的Daemon属性为true。
Thread t = new Thread(()->{
});
t.setDaemon(true);
t.start();
-
线程的等待(wait)和唤醒(notify/notifyAll),可以让获得synchornized的线程通过调用wait方法进入到锁的等待池中,并释放该线程的锁资源;可以让获取synchornized的线程调用notify或notifyAll方法,将等待池中的线程唤醒,进入到锁池中去竞争锁资源。notify方法时随机唤醒一个线程,notifyAll唤醒所有的线程
-
在调用wait、notify、notifyAll时,必须要在有synchornized修饰的代码块中调用,否则会抛异常,因为是要操作某个对象的锁信息。
-
线程的结束方式,return或抛异常均可实现线程的结束。
-
stop()(强制不要使用该方式),强制结束线程
-
使用共享变量,破坏死循环,不常用
-
static volatile flag =true;
public static void main(String[] args){
Thread t = new Thread(()->{
while(falg){
// 处理任务
}
})
t.start();
flag = false;
}
- interrupt方式,最常用的方式
// 线程默认的打断标记位是false的
Thread.currentThread().isInterrupt();
//执行线程打断
Thread.currentThread().interrupt();
// 返回当前线程的interrupt标记位,并归位为false
Thread.interrupted();
// 此时输出false
Thread.interrupted();