线程
线程是什么?线程和进程有什么区别?
回答什么是线程那么就需要先回答什么是进程?在我们执行程序的时候,系统就会为进程分配一些资源,如内存、磁盘、IO等,所以进程是系统分配资源最基本的单位。
那么线程呢?线程是进程中执行程序最小的单位,也就是说当程序开始执行时,系统会先为进程分配资源,然后进程会让自己下面的线程去执行具体的程序,所以进程中会包括线程,线程是进程的一部分,而且一个程序最少有一个进程,一个进程最少有一个线程,
那么为什么不直接使用进程来执行程序,非得要先让进程分配任务给线程让线程来执行程序呢?
为了减少资源的消耗。当程序执行时,系统会为进程分配地址空间,分配资源,还要记录相关信息,这些都非常的消耗资源,所以不能开启过多的进程,当执行程序时需要执行者之间不断地进行通信和切换,进程之间的通信消耗相比较而言更大,而且线程之间共享全局变量和静态变量等特性也决定了线程对资源的消耗比进程要小,所以执行程序时应该优先使用线程而不是进程。
那么进程有什么优点,线程有什么缺点呢?
因为进程有自己的独立空间,那么当一个进程崩溃后在保护模式下不会对其他的进程产生影响,而线程只是进程中不同的执行路线,虽然有自己的堆栈和局部变量,但是线程空间没有单独的地址空间,所以一个线程如果出现问题,可能会导致整个程序出现问题。最后得出结论,进程更健壮,线程与进程相比不太稳定
线程有什么状态呢?
初始:新建一个线程对象,但是没有调用start()方法
运行:处于可运行状态的线程在jvm中执行
阻塞:线程阻塞于synchronized锁,等待获取synchronized锁的状态
等待:进入该状态的线程需要等待其他线程做出一些特定的动作
超时等待:在等待期间可以在指定的时间内自行返回
终止:该线程已经执行完毕。
如何去创建一个线程呢?
两种方法:
- 继承Thread类,实现相应的run方法
public class Thread02 extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread02 thread = new Thread02();
thread.setName("线程1");
thread.start();
}
}
- 实现Runable接口,并实现run方法
public class Thread03 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread02 thread = new Thread02();
thread.setName("线程2");
thread.start();
}
}
在实际开发中建议使用第二种,因为java中不支持多继承,但是支持多实现,所以是用第二种可以提高代码的健壮性。
第三种:匿名内部类
public class Thread04 {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
}
});
thread.start();
}
}
第四种:lambda表达式
public class Thread05 {
public static void main(String[] args) {
new Thread(()->{
System.out.println(Thread.currentThread().getName());
}).start();;
}
}
第五种:线程池
public class Thread06 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
}