- 终止状态: 线程执行完或者出现异常或者调用API强制结束。
Java语言中线程共有六种状态,分别是:
-
NEW(初始化状态) : Java刚创建出来的Thread对象。
-
RUNNABLE(可运行/运行状态) : Thread执行start()方法。
-
BLOCKED(阻塞状态),WAITING(无时限等待),TIMED_WAITING(有时限等待) : RUNNABLE状态的线程调用wait()、join()、sleep()方法。
-
TERMINATED(终止状态): run()方法执行完,或者意外中断。
BLOCKED,WAITING,TIMED_WAITING 是上面提到的休眠状态。Java线程处于这些状态那么这个线程就永远没有CPU的使用权。
创建一个线程线程可以通过isInterrupted()方法,检 测是不是自己被中断了。
Java刚创建出来的Thread对象就是NEW状态,而创建Thread对象主要有两种方法。一种是继承Thread对 象,重写run()方法。示例代码如下:
方式一: 继承Thread
// ⾃定义线程对象
class MyThread extends Thread{
public void run() {
// 线程需要执⾏的代码
}
}
// 创建线程对象
MyThread myThread = new MyThread();
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】 浏览器打开:qq.cn.hn/FTf 免费领取
方式二: 实现Runnable接口
//实现Runnable接⼝
class Runner implements Runnable {
@Override
public void run(){
//线程需要执⾏的代码
}
}
//创建线程对象
Thread thread = new Thread(new Runner());
方式三:实现Callable接口
//实现Runnable接⼝
class Runner implements Callable {
@Override
public String call() throws Exception {
//线程需要执⾏的代码
return null;
}
}
//创建 FutureTask
FutureTask ft1 = new FutureTask(new Runner());
//执行这个任务
Thread t1 = new Thread(ft1);
t1.start();
//获取返回值
t1.get();
方法三实质上也是实现了Runnable接口,因为FutureTask实现了Runnable接口
Future接口提供的方法:
// 取消任务
boolean cancel(boolean mayInterruptIfRunning);
// 判断任务是否已取消
boolean isCancelled();
// 判断任务是否已结束
boolean isDone();
// 获得任务执⾏结果
get();
// 获得任务执⾏结果,⽀持超时
get(long timeout, TimeUnit unit);
这两个get()方法都是阻塞式的,如果被调用的时候,任务还没有执行完,那么调用get()方法的线程会阻塞,直到任务执行完才会被唤醒。
-
Java刚创建出来的Thread对象就是NEW状态
-
NEW状态的线程不会被操作系统调度,因此不会执行
-
NEW状态的线程调用start()会进入RUNNABLE状态
stop()会杀死线程,如果线程持有ReentrantLock锁,被stop()的线程并不会自动调用ReentrantLock的unlock()去释放锁,那其他线程就再也没机会获得ReentrantLock锁。所以该方法就不建议使用了,类似的方法还有suspend()和resume()方法,这两个方法同样也都不建议使用。
interrupt()仅仅是通知线程,线程有机会执行一些后续操作,同时也可以无视这个通知。
为什么要使用多线程提高程序的性能: 降低延迟,提高吞吐量。
提高性能的方式:1优化算法;2将硬件的性能发挥到极致
在并发编程领域,提升性能本质上就是提升硬件的利用率,具体来说就是提升I/O的利用率和CPU的利用率。
如果CPU和I/O设备的利用率都很低,那么可以尝试通过增加线程提高吞吐量。
创建多少线程合适?我们的程序一般都是CPU计算和I/O操作交叉执行的,由于I/O设备的速度相对于CPU来说都是很慢的,所以大部分情况下,I/O操作的执行时间相对于CPU计算来说都非常长,这种场景我们一般都成为I/O密集型程序和CPU密集型程序,计算最近线程数的方法是不同的。
对于CPU密集型的计算场景,理论上“线程的数量=CPU核数”就是最合适的。不过在工程上,线程的数量一般会设置为"CPU核数+1" ,这样的话,当线程因为偶尔的内存页失效或其他原因导致阻塞时,这个额外的线程可以顶上,从而保证CPU的利用率。



