文章目录
线程和进程的概念
进程 :是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元;
线程:就是进程中的一个独立控制单元,线程在控制着进程的执行。一个进程中至少有一个线程。
多线程:一个进程中不只有一个线程。
线程是一个程序内部的顺序控制流,可以理解为程序的不同执行路径。
线程的创建
1、继承Thread类:
- 继承Thread类
- 重写run方法,run方法执行结束,此线程结束
- 执行start()方法,启动线程
示例1:
public class Test1 {
public static void main(String[] args) {
MyThread1 t1=new MyThread1();
t1.run();
System.out.println("-------main----------");
}
}
class MyThread1 extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(i);
}
}
}
执行结果:
0
1
2
3
4
5
6
7
8
9
-------main----------
分析:如果执行run方法,并没有启动除了main之外其他线程,在执行run()方法之后,按照主线程顺序执行。
示例2:
public class Test1 {
public static void main(String[] args) {
MyThread1 t1=new MyThread1();
// t1.run();
t1.start();
System.out.println("-------main----------");
}
}
class MyThread1 extends Thread{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(i);
}
}
}
执行结果:
-------main----------
0
1
2
3
4
5
6
7
8
9
分析:如果执行start()方法,启动了其他线程,此线程和主线程同时执行。
2、实现Runnable接口:
类必须定义一个称为run 的无参方法。
- 实现Runnable接口
- 实现run()方法
- 使用Thread创建一个线程对象,将实现Runable的子类对象传递给Thread的构造函数
- 执行start(),启动线程
示例:
public class Test2 {
public static void main(String[] args) {
MyThread2 t2 = new MyThread2();
Thread thread=new Thread(t2);
thread.start();
System.out.println("-------main----------");
}
}
class MyThread2 implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}
3、通过Callable和Future创建线程:
- 实现Callable接口
- 实现call方法
- 使用FutureTask对象作为Thread对象启动新线程
- 使用FutureTask对象的get()获取执行结果(获取运算结果是同步过程,即 call 方法执行完成,才能获取结果,不获取就是异步)
示例:
public class Test3 {
public static void main(String[] args) throws Exception {
MyThread3 t3 = new MyThread3();
FutureTask futureTask=new FutureTask(t3);
new Thread(futureTask).start();
Object o = futureTask.get();//获取运算结果是同步过程,即 call 方法执行完成,才能获取结果,不获取就是异步
System.out.println("-------main----------");
}
}
class MyThread3 implements Callable {
//必须有返回值
public Object call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
return null;
}
}
继承Thread类和实现Runnable接口、实现Callable接口的区别
继承Thread:线程代码存放在Thread子类run方法中。
优势:编写简单,可直接用this.getname()获取当前线程,不必使用Thread.currentThread()方法。
劣势:已经继承了Thread类,无法再继承其他类。
实现Runnable:线程代码存放在接口的子类的run方法中。
优势:避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
劣势:比较复杂、访问线程必须使用Thread.currentThread()方法、无返回值。
实现Callable:
优势:有返回值、避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
劣势:比较复杂、访问线程必须使用Thread.currentThread()方法
一般使用实现接口的方式创建多线程
线程的生命周期(状态)
- New
- Runnable(分为Ready就绪跟Running执行状态)
- TimedWaiting:超时等待状态
- Waiting:等待状态
- Blocked:阻塞状态,等待获取锁
- Terminated:终止状态
线程的常用方法
休眠sleep()
Thread.sleep(long millis):此线程休眠多少毫秒,在哪个线程里面写,休眠哪个线程
合并线程join()
当A线程执行到B线程的join方法时,先让B执行完,再执行A
高风亮节让其他线程先执行yield()
使线程暂停一下,高风亮节让其他线程先执行,用的较少。
线程优先级设置
t1.setPriority(Thread.NORM_PRIORITY+3),设置此线程的优先级比正常高3。
stop()
暴力终止线程,不建议使用。