Thread有六个生命周期
创建时
,它处于新建状态。在这个阶段,线程还没有启动。public static void main(String[] args) throws Exception{
System.out.println("Thread State is:"+new Thread().getState());
}
start()
方法后,线程进入就绪状态。在就绪状态下,线程已经准备好运行,但还没有得到 CPU 时间片。public static void main(String[] args) {
new Thread(() -> {
System.out.println("Thread State is:"+Thread.currentThread().getState());
}).start();
}
获得CPU时间片
后,进入运行状态。在运行状态下,线程执行具体的任务代码。放弃CPU时间片
,进入阻塞状态。例如,线程等待某个资源的释放,或者调用了sleep()方法。public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();//锁
BlockThread t1 = new BlockThread(lock,"T1");
BlockThread t2 = new BlockThread(lock,"T2");
t1.start(); //线程 T1开始运行
t2.start(); //线程 T2开始运行
Thread.sleep(100); //阻塞主线程,等待T1,T2抢锁
System.out.println("Thread T1 State is " + t1.getState()); //获取T1线程状态
System.out.println("Thread T2 State is " + t2.getState()); //获取T2线程状态
}
}
class BlockThread extends Thread {
private String name; //当前线程名称
private Object lock; //锁
public BlockThread(Object lock, String name) {
this.lock = lock;
this.name = name;
}
@Override
public void run() {
System.out.println("Thread " + name + " State is " + Thread.currentThread().getState());
synchronized (lock) {
System.out.println("Thread " + name + " hold the lock");
try {
System.out.println("Thread " + name + " State is " + Thread.currentThread().getState());
Thread.sleep(1000 * 10); //抢到锁的线程执行逻辑,这里用睡眠模拟
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread " + name + " release the lock");
}
}
}
等待某个条件的触发时
进入等待状态。例如,调用Object.wait()方法或者 Thread.join()方法。public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
WaitingThread t = new WaitingThread("T", lock);
t.start();
Thread.sleep(1000);
System.out.println("Thread T State is " + t.getState());
System.out.println("Thread "+Thread.currentThread().getName()+" State is " + Thread.currentThread().getState());
}
}
class WaitingThread extends Thread {
private Object lock;
public WaitingThread(String name, Object lock) {
super(name);
this.lock = lock;
}
@Override
public void run() {
System.out.println("Thread " + Thread.currentThread().getName()+" try to wait");
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
阻塞和等待的区别
阻塞状态 | 等待状态 | |
---|---|---|
原因 | 当线程试图获得一个对象的锁, 但该锁已经被其他线程持有时, 线程会进入阻塞状态 | 当线程在某个对象上调用Object.wait()方法时, 它会进入等待状态, 等待期间会释放对象的锁 |
解除 | 当持有锁的线程释放锁时, 被阻塞的线程有机会重新竞争锁, 并进入就绪状态 | 线程可以通过调用Object.notify()或Object.notifyAll()来被唤醒,也可以在等待期间等待超时 |
是否会释放持有的锁 | 在阻塞状态下, 线程仍然保持对锁的所有权 | 在等待状态下, 线程会释放锁, 让其他线程有机会获得锁 |
阻塞状态结束后, 线程重新进入就绪状态,
在等待状态中, 线程可以被唤醒, 被唤醒的线程将重新进入就绪状态, 并尝试获取对象的锁
Thread() :创建一个默认设置的线程对象实例
Thread(Runnable target) :创建一个包含可执行对象的线程实例
Thread(Runnable target, String name) :创建一个包含可执行对象,指定名称的线程对象
Thread(String name):创建一个指定名称的线程对象
Thread(ThreadGroup group, Runnable target) :创建一个指定线程组,包含可执行对象的线程对象实例
Thread(ThreadGroup group, Runnable target, String name) :创建一个指定线程组,包含可执行对象,指定线程名称的线程对象实例
Thread(ThreadGroup group, Runnable target, String name, long stackSize) :创建一个指定线程组、包含可执行对象、指定名称以及堆栈大小的线程对象实例
Thread(ThreadGroup group, String name):创建一个指定线程组,线程名称的线程实例
1.继承Thread类
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
// 继承Thread
MyThread thread1 = new MyThread();
thread1.start();
// 匿名内部类
Thread thread2 =new Thread() {
@Override
public void run() {
System.out.println("Hello World 2");
}
};
thread2.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello World");
}
}
2.实现Runnable接口
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
// 继承Thread
Thread thread1 = new Thread(new MyRunnable());
thread1.start();
// 匿名内部类
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello World 2");
}
});
thread2.start();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Hello World");
}
}
3.实现Callable接口
FutureTask 是一个类,它实现了 Runnable 和 Future 接口
Callable不能直接交给Thread来运行, 我们可以使用FutureTask包装Callable, 让它变成一个Runnable
public class FutureTaskThreadDemo {
public static void main(String[] args) {
// 创建一个实现 Callable 接口的匿名类实例,该实例在 call() 方法中返回一个字符串
Callable<String> callableTask = new Callable<String>() {
@Override
public String call() throws Exception {
// 在这里执行你的任务,并返回结果
String result = "Hello from Callable!";
return result;
}
};
// 使用 Callable 任务创建一个 FutureTask 实例
FutureTask<String> futureTask = new FutureTask<>(callableTask);
// 创建一个新线程,并将 FutureTask 作为参数传递给它
Thread taskThread = new Thread(futureTask);
// 启动新线程,这将执行 FutureTask 中的 Callable 任务
taskThread.start();
try {
// 从 FutureTask 对象中获取计算结果,如果任务尚未完成,此方法会阻塞等待
String result = futureTask.get();
System.out.println("Result: " + result);
} catch (InterruptedException e) {
// 当前线程在等待过程中被中断时抛出 InterruptedException
e.printStackTrace();
} catch (ExecutionException e) {
// 计算任务抛出异常时抛出 ExecutionException
e.printStackTrace();
}
}
}
添加链接描述
1.join
join()方法, 作用是让一个线程等待另一个线程执行结束
如果线程A中调用了线程B的join()方法, 那么线程A将会等待线程B执行完成, 然后再继续执行
join方法有以下几个特点:
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new MyRunnable(), "Thread-1");
Thread thread2 = new Thread(new MyRunnable(), "Thread-2");
// 启动线程1
thread1.start();
thread1.join();
// 启动线程2
thread2.start();
}
}
class MyRunnable implements Runnable {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
Thread.sleep(100); // 模拟一些耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}