1.什么是线程
在并发编程中,有两个基本的执行单元:进程和线程。在Java编程语言中,并发编程主要关注线程。
线程有时称为轻量级进程。进程和线程都提供了一个执行环境,但创建一个新线程所需的资源要少于创建新进程的资源。
线程存在于一个进程中, 每个进程至少有一个线程。线程共享进程的资源,包括内存和打开的文件。这使得沟通有效但可能有问题。
2.线程生命周期
- 新建状态(New):新创建了一个线程对象。
- 就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
- 运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
-
阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一). 等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)
(二). 同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三). 其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。(注意,sleep是不会释放持有的锁) - 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
3.定义和启动线程
定义线程有两种方式:
- 实现Runnable接口
- 继承Thread类
//实现Runnable接口
public class RunnableImpl implements Runnable {
@Override
public void run() {
System.out.println("测试");
}
public static void main(String[] args) {
new Thread(new RunnableImpl()).start();
}
}
//继承Thread类
public class ThreadTest extends Thread {
@Override
public void run() {
System.out.println("测试");
}
public static void main(String[] args) {
new ThreadTest().start();
}
}
启动线程都是通过调用Thread.start方法
4.sleep
提供了两种sleep:
- 指定休眠时间为毫秒(sleep(long millis))
- 指定休眠时间为毫秒+纳秒(sleep(long millis, int nanos))
注意:这些睡眠时间并不能保证准确,因为它们受底层操作系统提供的设施的限制。
5.interrupt
一个中断是指示线程它应该终止它在做什么和做别的事情。由程序员来决定线程是如何响应中断的,但线程终止是非常常见的。
线程通过interrupt在Thread对象上调用中断线程来发送中断。为使中断机制正常工作,被中断的线程必须支持自己的中断。
中断状态标志
中断机制通过一个称为中断状态的内部标志来实现。调用Thread.interrupt设置此标志。当线程通过调用静态方法检查中断时Thread.interrupted,中断状态被清除。isInterrupted一个线程用于查询另一个线程的中断状态的非静态方法不会更改中断状态标志。
支持中断
支持中断的方式:
- 在捕获异常后return
- 定期判断是否中断,是,就return或抛出中断异常,然后通过调用interrupt发送中断
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("线程中断");
return;
}
if(Thread.interrupted()){
System.out.println("线程中断");
return;
}
if(Thread.interrupted()){
System.out.println("线程中断");
throw new InterruptedException();
}
6.join
线程A调用join方法时,会导致当前线程(也就是创建线程A所在的线程)暂停执行,直到线程A终止。
public class ThreadTest extends Thread {
@Override
public void run() {
System.out.println(this.getName()+"加入");
for (int i = 0; i < 4; i++) {
try {
Thread.sleep(1000);
System.out.println(this.getName()+"执行");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("异常");
}
}
System.out.println(this.getName()+"结束");
}
public ThreadTest(String name) {
super(name);
}
public static void main(String[] args) {
System.out.println("主线程执行");
ThreadTest t = new ThreadTest("猴子");
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程结束");
}
}
网友评论