1.sleep
public static void sleep(long millis) throws InterruptedException //millis:毫秒数
public static void sleep(long millis, int nanos) throws InterruptedException //millis:毫秒数, nanos:纳秒数
会使当前线程进入指定毫秒数休眠,暂停执行,并且不会放弃monitor锁的所有权
Thread.sleep()只会导致当前线程进入睡眠
2.TimeUnit
Thread.sleep(12257088L) == TimeUnit.HOURS.sleep(3); TimeUnit.MINUTES.sleep(24); TimeUnit.SECOND.sleep(17); TimeUnit.MILLISECONDS.sleep(88);
是休眠的util类,更加方便
3.yield
是一种启发式方法,提醒调度器我愿意放弃当前的cpu资源,如果cpu资源不紧张,则会忽略这种提醒
调用yield方法会使当前线程从running状态到runnable状态
4.yield和sleep的区别
(1)sleep会导致当前线程暂停指定的时间,没有cpu时间片的消耗
(2)yield只是对cpu调度器的一个提示,如果cpu调度器没有忽略这个提示,它会导致线程上下问的切换
(3)sleep会使线程短暂block,会在给定的时间内释放cpu资源
(4)yield会使running状态的thread进入runnable状态(如果cpu调度器没有忽略这个提示的话)
(5)sleep几乎百分百地完成了给定时间的休眠,而yield的提示并不能一定担保
(6)一个线程sleep另一个线程调用interrupt会捕获到中断信号,而yield则不会
5.设置线程的优先级
public final void setPriority(int newPriority) 设置线程的优先级
public find int gettPriority() 获取线程的优先级
newPriority 介于[1, 10]之间,如果指定的线程优先级大于线程所在的group优先级,那么指定的优先级将会失效,取而代之的是group的最大优先级,默认优先级和它父类保持一致,一般是5,因为main线程的优先级就是5
如果cpu比较闲,设置优先级几乎没作用,所以不要依赖于设置优先级
6.获取线程id
public long getId() 获取线程唯一的id,在整个jvm中id是唯一的
7.获取当前线程
public static Thread currentThread() 用于返回当前线程的索引,
8.设置线程上下文类加载器
public ClassLoader getContextClassLoad() 获取线程上下文的类加载器,就是当前线程是由哪个类加载器加载的,如果没有指定,那么保持和父线程同样的类加载器
public void setClassLoader(ClassLoad cl) 设置该线程的类加载器,可以打破java类加载器的父委托机制,也被成为java类加载器的后门
9.线程中断(interrupt)
public void interrupt()
public static boolean interrupted()
public boolean isInterrupted()
interrupt会打断线程执行wait(...),sleep(...),join(...),io操作,wakeup方法造成的阻塞
如果线程在阻塞状态被打断,那么会抛出一个Interrupted Exception 的异常,如果线程死亡,那么执行interrupt将会无效
public class ThreadInterrupt { public static void main(String[] args) { Thread thread = new Thread(() -> { try { TimeUnit.MINUTES.sleep(1); } catch (InterruptedException e) { System.out.println("oh, i am be interrupted"); } }); thread.start(); try { TimeUnit.MILLISECONDS.sleep(2); thread.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } } }
thread.isInterrupted()会判断线程是否中断,并且擦除interrupt标识,也就是说第一次调用thread.isInterrupted()方法,会返回true,但是第二次调用时,就会永远返回false
10.线程join
属于一个中断方法
public final void join() throws InterruptedException
public final synchronized void join(long millis, int nanos) throws InterruptedException
public final synchronized void join(long millis) throws InterruptedException
join某个线程a, 会使当前线程b进入等待,等待线程a结束生命周期,或者到达给定的时间,那么当时b线程进入blocked状态
public interface FightQuery { List<String> get(); }
public class FightQueryTask extends Thread implements FightQuery { private final String origin; private final String destination; private final List<String> flightList = new ArrayList<>(); public FightQueryTask(String airline, String origin, String destination) { super("[" + airline + "]"); this.origin = origin; this.destination = destination; } @Override public void run() { System.out.println("query from:" + getName() + " " + origin + " " + destination); int randomVal = ThreadLocalRandom.current().nextInt(10); try { TimeUnit.SECONDS.sleep(randomVal); this.flightList.add(getName() + "-" + randomVal); System.out.printf("the fight:%s list query successful ", getName()); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public List<String> get() { return this.flightList; } }
public class FightQueryExample { //合作的各大航空公司 private static List<String> fightCompany = Arrays.asList( "csa", "cea", "hna" ); public static void main(String[] args) { List<String> results = search("sh", "bj"); System.out.println("==========result============"); results.forEach(System.out::println); } private static List<String> search(String orignal, String dest) { final List<String> result = new ArrayList<>(); //创建查询航班信息的线程列表 List<FightQueryTask> tasks = fightCompany.stream().map(f -> createSearchTask(f, orignal, dest)).collect(Collectors.toList()); //分别启动这些线程 tasks.forEach(Thread::start); //分别调用每一个线程的join方法,阻塞当前线程 tasks.forEach(t -> { try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } }); //在此之前,当前线程会阻塞住,获取每一个查询线程的结果,并且加入到result中 tasks.stream().map(FightQueryTask::get).forEach(result::addAll); return result; } private static FightQueryTask createSearchTask(String fight, String orignal, String dest) { return new FightQueryTask(fight, orignal, dest); } }
有点难,反正我是不会。。。。
11.关闭线程
(1)正常关闭
线程结束生命周期正常关闭
捕捉中断信号关闭线程
public class InterruptThreadExit { public static void main(String[] args) { Thread t = new Thread() { @Override public void run() { System.out.println("i will start work"); while (!isInterrupted()) { //working } System.out.println("i will be finishing"); } }; t.start(); try { TimeUnit.MILLISECONDS.sleep(1); System.out.println("system will be shutdown"); t.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } } }
使用volatile开关控制
public class FlagThreadExit { static class MyTask extends Thread { private volatile boolean closed = false; @Override public void run() { System.out.println("i will start work"); while (!closed && !isInterrupted()) { //正在运行 } System.out.println("i will be existing"); } public void close() { this.closed = true; this.isInterrupted(); } } public static void main(String[] args) { MyTask myTask = new MyTask(); myTask.start(); try { TimeUnit.MILLISECONDS.sleep(1); System.out.println("system will be shutdown"); myTask.close(); } catch (InterruptedException e) { e.printStackTrace(); } } }
(2)非正常关闭
异常退出
在线程执行过程中,是不允许抛出checked异常的
进程假死