1. Thread 类、常见方法
1.1 常用构造方法
| 方法 | 说明 |
|---|---|
| Thread() | 创建线程对象 |
| Thread( Runnable target) | 使用 Runnable 对象创建线程对象 |
| Thread(String name) | 创建线程对象并命名 |
| Thread( Runnable target ,String name) | 使用 Runnable 对象创建线程对象,并命名 |
1.2 线程的常见属性
| 属性 | 获取方法 |
|---|---|
| ID | getId() |
| 名称 | getNname() |
| 状态 | getState() |
| 优先级 | getPriority() |
| 是否是后台线程 | isDaemon() |
| 是否存活 | isAlive() |
| 是否中断 | isInterrupted() |
获取线程的名称
Threadt1=newThread();//给线程起名字Threadt2=newThread("线程2");Threadt3=newThread(newRunnable(){@Overridepublicvoidrun(){}},"线程3");//getName 获取线程的名字System.out.println(t1.getName());System.out.println(t2.getName());System.out.println(t3.getName());线程的名字默认是
Thread - 数字, 给线程起名字,可以在线程数量很多的情况下,更方便地观察线程
1.3 前台线程和后台线程
- 前台线程 : 会阻止进程的结束
- 后台线程 : 不会阻止进程的结束
publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(()->{for(inti=0;i<5;i++){System.out.println("thread");try{// 睡眠 1 秒Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}}System.out.println("t线程结束");});t.start();// 睡眠 1 秒Thread.sleep(1000);System.out.println("主线程结束");// main 和 t 都是前台线程 2 个线程都结束 进程才结束}进程默认就是前台线程,可以通过
setDaemon(true)把线程设置为 后台线程
参数是 true 表示是后台线程, 默认是 false 表示前台线程;要在线程开启前设置
publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(()->{for(inti=0;i<5;i++){System.out.println("thread");try{// 睡眠 1 秒Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}}System.out.println(" t 线程结束");});// 在 strat() 开始前 把 t 设置成 后台线程(守护线程)t.setDaemon(true);t.start();// 睡眠 1 秒Thread.sleep(1000);System.out.println("主线程结束");// 前台线程结束了 进程就结束}1.4 start( )
strart()会调用操作系统的 API , 在操作系统中创造出一个线程
Java为了让一个 thread 对象和 一个操作系统线程 一一对应, 每个线程只能调用一次start()
publicstaticvoidmain(String[]args){Threadt1=newThread(()->{System.out.println("t1 thread");});t1.start();t1.start();}1.5 中断线程
中断线程的 2 种方式 :
- 通过共享标记进行沟通
- 通过调用 interrupt( ) 方法
使用自定义变量作为标识位
privatestaticbooleanrunning=true;publicstaticvoidmain(String[]args){Threadt=newThread(()->{while(running){System.out.println("thread t");try{Thread.sleep(1000);}catch(InterruptedExceptione){thrownewRuntimeException(e);}}});t.start();try{//睡眠 4 秒后 中断线程Thread.sleep(4000);running=false;}catch(InterruptedExceptione){thrownewRuntimeException(e);}}使用 interrupt( )
publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(()->{// currentThread 获取 t 线程的引用Threadcur=Thread.currentThread();//isInterrupted 判断 t 线程的标识位while(!cur.isInterrupted()){System.out.println("thread");try{//预计 sleep 100 秒Thread.sleep(100_000);}catch(InterruptedExceptione){e.printStackTrace();}}});t.start();Thread.sleep(1000);// 设置 t 线程的标识位t.interrupt();}
interrupt()能设置标志位,还能唤醒 sleep 等导致线程堵塞的方法
Q :为什么这里会在线程中止后又打印 thread ?
A :interrupt()设置标识位为true唤醒sleep(),让sleep()抛出异常后,sleep()自动重新设置标识位为false
Thread.currentThread(): 获取当前线程的引用publicstaticvoidmain(String[]args){//获取主线程的引用ThreadmainThread=Thread.currentThread();System.out.println(mainThread.getName());}如果在主线程执行
Thread.currentThread()就是获取主线程的引用;
在thread1线程中执行Thread.currentThread()就是获取thread1线程的引用
1.6 join( ) 线程等待
privatestaticintsum=0;publicstaticvoidmain(String[]args){Threadt=newThread(()->{for(inti=1;i<=1000;i++){sum+=i;}});t.start();System.out.println("sum = "+sum);}要求是 :等t 线程计算完1~1000的和之后, 主线程再进行打印和
结果是
t线程还没有计算, 主线程就打印结果了,如果使用sleep()让 主线程睡一会,睡少了t 线程还没有计算完,睡多了又浪费时间,另外如果t 线程的逻辑复杂,sleep()就更不适用,这时使用join()就能让一个线程执行结束后,再继续执行
| 方法 | 说明 |
|---|---|
| join() | 当前线程一直等待,直到目标线程执行完毕才继续 |
| join( long millis ) | 当前线程最多等待 millis 毫秒,超时后无论目标线程是否结束,当前线程都会继续执行 |
privatestaticintsum=0;publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(()->{for(inti=1;i<=1000;i++){sum+=i;}});t.start();t.join();System.out.println("sum = "+sum);}
join()如果目标线程一直不结束,那就会一直等下去
publicstaticvoidmain(String[]args)throwsInterruptedException{//获取 main 线程的引用Threadmain=Thread.currentThread();System.out.println("开始等待");main.join();System.out.println("线程结束");}
join( long millis )等待设置的 ms 后继续执行
publicstaticvoidmain(String[]args)throwsInterruptedException{//获取 main 线程的引用Threadmain=Thread.currentThread();System.out.println("开始等待");//等待 2 秒main.join(2000);System.out.println("线程结束");}如果调用
join前线程就已经执行完了,再次调用join是线程不会堵塞
2. 线程的状态
线程的 6 种状态
| 状态 | 表示 |
|---|---|
| NEW | 创建了 Thread 对象但没有 start() |
| TERMINATED | 操作系统线程销毁(线程的执行入口执行完了),但 thread 对象还在 |
| RUNNABLE | 可运行的 1.CPU 正在执行 2.等待CPU调度执行(就绪) |
| WAITING | 线程无限等待 调用无参 join(),目标线程不结束,等待进程的状态 |
| TIMED_WAITING | 线程有限等待 调用join(long millis) 过程中,等待进程的状态 |
| BLOCKED | 由于锁导致的堵塞 |
NEW 、RUNNABLE 、TERMINATED 状态的转换
publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(()->{});System.out.println(t.getState());t.start();System.out.println(t.getState());t.join();System.out.println(t.getState());}WAITING
publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadmainThread=Thread.currentThread();Threadt=newThread(()->{while(true){System.out.println("mainThread state "+mainThread.getState());}});t.start();t.join();}TIMED_WAITING
publicstaticvoidmain(String[]args)throwsInterruptedException{ThreadmainThread=Thread.currentThread();Threadt=newThread(()->{while(true){System.out.println("mainThread state "+mainThread.getState());}});t.start();t.join(10000);}