前言
Thread 类是 Java 中用于创建和管理线程的类。在 Java 中,每个程序至少有一个线程,也就是主线程。使用 Thread 类,可以创建新的线程并与主线程并行执行.Thread类的基本用法有以下几种方式:
Thread类的基本用法有以下几种方式:
1.继承Thread类
class Mythread extends Thread{
@Override
public void run() {
//这个方法是线程的入口方法
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
Thread t =new Mythread();
//t.run();
t.start();
while (true){
System.out.println("hello main");
Thread.sleep(1000);
}
}
}
2. 继承Thread匿名内部类
public class Demo2 {
public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run() {
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
t.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
3.实现Runnable接口
class MyRunnable implements Runnable{
@Override
public void run() {
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
public class Demo3 {
public static void main(String[] args) {
Runnable runnable =new MyRunnable();
Thread t =new Thread(runnable);
t.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
与直接继承Thread的区别是,这个方法能解耦合,如果一个类需要运行在一个新的线程上,那么通过实现Runnable接口,我们可以把这个类和Thread类进行解耦合,这样修改这个类的代码就不需要修改Thread类的代码,反之亦然.
4.实现Runnable接口匿名内部类
public class Demo4 {
public static void main(String[] args){
Runnable runnable = new Runnable() {
@Override
public void run() {
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
};
Thread t =new Thread(runnable);
t.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
5 .使用Lambda表达式
public class Demo5 {
public static void main(String[] args) {
Thread t =new Thread(() ->{
while (true){
System.out.println("hello thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
while (true){
System.out.println("hello main");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
二.线程的中断
目前常见的有以下两种方式:
1. 通过共享的标记来进行沟通
public class Demo6 {
private static volatile boolean isQuit = false;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
while (!isQuit) {
System.out.println("线程工作中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println("线程工作完毕");
});
t.start();
Thread.sleep(5000);
isQuit = true;
System.out.println("设置isQuit为true");
}
}
这个方式需要给标志位上加 volatile 关键字,确保isQuit的可见性.
2.使用Thread自带的标志位来控制线程是否要停止
public class Demo7 {
public static void main(String[] args){
Thread t = new Thread(()->{
//Thread 类内部有一个现成的标志位,可以用来判定当前的循环是否要结束
while (!Thread.currentThread().isInterrupted()){
System.out.println("线程工作中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("让t线程中止");
t.interrupt();
}
}
如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通
知,清除中断标志
当出现
InterruptedException
的时候
,
要不要结束线程取决于
catch
中代码的写法
.
可以选择
忽略这个异常
,
也可以跳出循环结束线程.如果你希望在线程t休眠时立即中断它,那么你可以在调用
Thread.sleep(1000)
的地方捕获InterruptedException异常,并在捕获到异常后立即退出循环,例如:
public class Demo8{
public static void main(String[] args){
Thread t = new Thread(()->{
//Thread 类内部有一个现成的标志位,可以用来判定当前的循环是否要结束
while (!Thread.currentThread().isInterrupted()){
System.out.println("线程工作中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 如果线程被中断,立即退出循环
break;
}
}
});
t.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("让t线程中止");
t.interrupt();
}
}
三.线程等待
用Thread中的join()方法来操作线程等待
public class Demo9 {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(()->{
for (int i = 0; i <5 ; i++) {
System.out.println("t线程工作中!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t.start();
//一旦调用join,主线程就会触发阻塞,让主线程来等待t线程执行结束
//一直阻塞到t执行完毕了,join才会解除阻塞,才能继续执行
System.out.println("join等待开始");
t.join();
System.out.println("join等待结束");
}
}
public void join()
等待线程结束
public void join(long millis)
等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos)
同理,但可以更高精度
四.线程休眠
在Java中,可以使用Thread.sleep()
方法来暂停当前线程的执行。这个方法需要一个表示休眠时间的参数,单位是毫秒。
public class Demo10 {
public static void main(String[] args) throws InterruptedException {
long beg =System.currentTimeMillis();
Thread.sleep(1000);
long end = System.currentTimeMillis();
System.out.println("时间"+(end -beg)+"ms");
}
}
因为线程的调度是不可控的,所以,这个方法只能保证实
际休眠时间是大于等于参数设置的休眠时间,而不能保证线程正好休眠1秒,它只能保证线程至少休眠1秒。
Thread.sleep
的时间参数是一个毫秒数,而操作系统的调度器是以毫秒为单位进行调度的,因此存在一定的误差。