一、创建线程的两种方式:
1、创建 java.lang.Thread 类的子类,重写该类的 run方 法
a、Thread类中的重要方法:
run方法:包括线程运行时执行的代码,通常在子类中重写它。
start方法:启动一个新的线程,然后虚拟机调用新线程的run方法
b、Thread 类代码示例
public class MyThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("线程" + getName() + "正在打印" + i);
}
}
public static void main(String[] args) {
String name = Thread.currentThread().getName();
System.out.println(name + "开始执行");
MyThread myThread = new MyThread();
myThread.start();
for (int i = 0; i < 100; i++) {
System.out.println("线程" + name + "正在打印" + i);
}
System.out.println("end");
}
}
2、创建 java.lang.Runnable接 口的实现类,实现接口中的 run 方法
a、Runnable 接口:
Runnable 接口中只有一个未实现的 run 方法,实现该接口的类必须重写该方法。
Runnable 接口与 Thread 类之间的区别
Runnable 接口必须实现 run 方法,而 Thread 类中的run 方法是一个空方法,可以不重写
Runnable 接口的实现类并不是真正的线程类,只是线程运行的目标类。要想以线程的方式执行 run 方法,必须依靠 Thread 类
Runnable 接口适合于资源的共享
b、Runnable 接口代码示例:
public class MyRunnable implements Runnable {
public void run() {
String name = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
System.out.println("线程" + name + "正在打印" + i);
}
}
public static void main(String[] args) {
String name = Thread.currentThread().getName();
System.out.println(name + "开始执行");
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println("线程" + name + "正在打印" + i);
}
System.out.println("end");
}
}
三、线程的生命周期:
新建状态(New)
当创建了一个Thread对象时,该对象就处于“新建状态”
没有启动,因此无法运行
可执行状态/就绪状态(Runnable)
其他线程调用了处于新建状态线程的start方法,该线程对象将转换到“可执行状态”
线程拥有获得CPU控制权的机会,处在等待调度阶段。
运行状态(Running)
处在“可执行状态”的线程对象一旦获得了 CPU 控制权,就会转换到“执行状态”
在“执行状态”下,线程状态占用 CPU 时间片段,执行run 方法中的代码
处在“执行状态”下的线程可以调用 yield 方法,该方法用于主动出让 CPU 控制权。线程对象出让控制权后回到“可执行状态”,重新等待调度。
阻塞状态(Blocking)
线程在“执行状态”下由于受某种条件的影响会被迫出让CPU控制权,进入“阻塞状态”。
进入阻塞状态的三种情况
调用sleep方法
调用join方法
执行I/O操作
死亡状态
线程的生命周期 示例
四、线程的同步和死锁(了解)
通过实现Runnable的线程,如果共享同一个资源,会出现同步问题:
如卖票时,会出现票数为负的情况
解决同步的方式:
死锁:
二个线程互相等待对方的释放对象占有的资源