1.基本概念:
1.1. 进程和线程的区别:
进程是线程的集合,线程是进程的一条执行路径
1.2. 什么是线程?
线程是一条执行路径,每条线程之间互不影响
1.3. 什么是多线程?
多线程在一个进程中,有多条执行路径,并行执行。目的是为了提高程序效率(因为现在都是多核多线程CPU,可以同时执行多个)
在一个进程中,一定会有的线程是:主线程(如果没有主线程,其他线程怎么创建出来的?)
1.4. 同步和异步
同步:代码中从上往下执行
异步:开了一个新的执行路径,进行执行
2.创建一个线程
2.1. 使用继承方式创建线程
/**
* 使用继承创建线程
*/
public class ThreadTest001 extends Thread{
@Override
public void run() {
for (int i=0;i<10;i++){
System.out.println("子....."+i);
}
}
public static void main(String[] args) {
System.out.println("主线程启动");
ThreadTest001 threadTest001 = new ThreadTest001();
threadTest001.start();//注意这里使用start是开启线程(异步),使用run是调用方法(同步)
for (int i=0;i<10;i++){
System.out.println("主....."+i);
}
System.out.println("主线程结束");
}
}
2.2.使用接口方式创建线程
/**
* 线程创建方式2.实现接口创建
*/
class ThreadTest0021 implements Runnable{
public void run() {
for (int i=0;i<10;i++){
System.out.println("子....."+i);
}
}
}
public class ThreadTest002 {
public static void main(String[] args) {
System.out.println("主线程启动");
ThreadTest0021 threadTest0021 = new ThreadTest0021();
Thread thread = new Thread(threadTest0021);
thread.start();
for (int i=0;i<10;i++){
System.out.println("主....."+i);
}
System.out.println("主线程结束");
}
}
注意这里启动没有start方法,需要new一个thread类,通过传入一个实现类的方式
2.3.使用匿名内部类方式创建线程
/**
* 使用匿名内部类的方式创建线程
*/
public class ThreadTest003 {
public static void main(String[] args) {
System.out.println("主线程启动");
Thread t1= new Thread(new Runnable() {
public void run() {
for (int i=0;i<10;i++){
System.out.println("子....."+i);
}
}
});
t1.start();
for (int i=0;i<10;i++){
System.out.println("主....."+i);
}
}
}
其中不推荐使用继承的方式创建,因为java继承只能继承一个类,而接口可以实现多个
3.多线程运行状态
新建状态:当new了一个thread后,还没有开启start之前的操作称为新建状态
就绪状态:当开启了start后,等待cpu进行调度的状态叫做就绪状态
运行状态:执行run方法里面的内容时候,称为运行状态
死亡状态:
有两个原因会导致线程死亡:
- run方法正常退出而自然死亡,
- 一个未捕获的异常终止了run方法而使线程猝死。
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.
阻塞状态:
1>线程通过调用sleep方法进入睡眠状态;
2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
3>线程试图得到一个锁,而该锁正被其他线程持有;
4>线程在等待某个触发条件;
4.守护线程和用户线程(非守护线程)
Java中有两种线程,一种是用户线程,另一种是守护线程。
用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止
守护线程当进程不存在或主线程停止,守护线程也会被停止。
使用setDaemon(true)方法设置为守护线程
jvm中的gc线程就是守护线程。当主线程死亡后,所有的gc线程也死亡
5.join()方法
有两个线程A,B。在线程B中调用A.join()方法,即等待A线程执行完毕后在执行(释放我的cpu执行权,让A先执行)
例:
现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行
public class JoinThreadDemo02 {
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("t1,i:" + i);
}
}
});
final Thread t2 = new Thread(new Runnable() {
public void run() {
try {
t1.join();
} catch (Exception e) {
// TODO: handle exception
}
for (int i = 0; i < 20; i++) {
System.out.println("t2,i:" + i);
}
}
});
Thread t3 = new Thread(new Runnable() {
public void run() {
try {
t2.join();
} catch (Exception e) {
// TODO: handle exception
}
for (int i = 0; i < 20; i++) {
System.out.println("t3,i:" + i);
}
}
});
t1.start();
t2.start();
t3.start();
}
}
这里调用内部类中的变量时候,要将该变量声明为final